fix: Abmelden ohne verspaetete Sync-Antwort (SDK-Wettlauf) + Live-Regressionstest
logoutWithoutStraySync (lib/core/session_logout.dart): Sync-Schleife anhalten, laufenden Long-Poll per Account-Daten wecken und auslaufen lassen, erst dann abmelden - es ist keine Anfrage mit altem Token mehr unterwegs, die per 401 ein zweites clear() ausloesen koennte. Genutzt an allen drei Abmelde-Stellen (Einstellungen, Ueber, Konto geloescht) und im E2E-Live-Test. Live gemessen: die verspaetete 401 tritt real auf, kam aber stets vor dem Abschluss einer Neuanmeldung an - Risiko war klein, ist jetzt ausgeschlossen. test/live_logout_race_test.dart in scripts/test.ps1 -Live. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f09e4875c6
commit
e90b954348
@@ -12,6 +12,7 @@ import 'package:matrix/matrix.dart';
|
||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||
import 'package:sqlite3/open.dart' as sqlite_open;
|
||||
import 'package:pyramid/core/app_database.dart';
|
||||
import 'package:pyramid/core/session_logout.dart';
|
||||
|
||||
/// LIVE-End-to-End-Test der SQLCipher-Verschlüsselung mit einem ECHTEN
|
||||
/// Matrix-Login gegen steggi-matrix.work (Test-Account, NICHT Bernd/Uta).
|
||||
@@ -207,23 +208,6 @@ Future<void> _login(Client client, _TestAccounts acc,
|
||||
);
|
||||
}
|
||||
|
||||
/// Logout ohne Nachzügler. matrix 6.2 prüft bei einer FEHLER-Antwort des
|
||||
/// Sync-Long-Polls nicht, ob die Anfrage noch aktuell ist: Läuft beim Logout
|
||||
/// noch ein Long-Poll mit dem alten Token, kommt dessen 401 (M_UNKNOWN_TOKEN)
|
||||
/// später zurück und das SDK ruft erneut `clear()`. Direkt nach einem
|
||||
/// Re-Login würde das die NEUE Session löschen, nach `dispose()` wirft es
|
||||
/// (DB geschlossen → Fallback auf die globale sqflite-Factory) – genau das
|
||||
/// machte diesen Test sporadisch rot (2026-10-07). Deshalb erst die
|
||||
/// Sync-Schleife anhalten, den laufenden Long-Poll regulär auslaufen lassen
|
||||
/// (≤ 30 s), dann abmelden. `clear()` schaltet backgroundSync wieder ein.
|
||||
Future<void> _logoutWithoutStraySync(Client client) async {
|
||||
client.backgroundSync = false;
|
||||
await client
|
||||
.oneShotSync(timeout: Duration.zero)
|
||||
.timeout(const Duration(seconds: 60));
|
||||
await client.logout();
|
||||
}
|
||||
|
||||
/// Holt (oder erzeugt) den unverschlüsselten Autopilot-Testraum.
|
||||
Future<Room> _ensureTestRoom(Client client) async {
|
||||
const roomName = 'Pyramid Autopilot Testraum';
|
||||
@@ -357,7 +341,7 @@ void main() {
|
||||
expect(client.userID?.toLowerCase(), acc.user1.toLowerCase());
|
||||
|
||||
// ── Phase 4: Logout → Re-Login → alte Nachricht wieder lesbar ──
|
||||
await _logoutWithoutStraySync(client);
|
||||
await logoutWithoutStraySync(client); // App-Baustein (session_logout.dart)
|
||||
expect(client.isLogged(), isFalse);
|
||||
await _login(client, acc,
|
||||
user: acc.user1, pass: acc.pass1, device: 'Autopilot Enc-Test 2');
|
||||
@@ -365,7 +349,7 @@ void main() {
|
||||
expect(await _timelineContains(roomAfter, marker), isTrue,
|
||||
reason: 'Alte Nachricht nach Logout+Re-Login nicht mehr lesbar');
|
||||
// Aufräumen: Session serverseitig beenden, DB wird dabei geleert.
|
||||
await _logoutWithoutStraySync(client);
|
||||
await logoutWithoutStraySync(client); // App-Baustein (session_logout.dart)
|
||||
await client.dispose(closeDatabase: true);
|
||||
},
|
||||
skip: skip,
|
||||
@@ -431,7 +415,7 @@ void main() {
|
||||
expect(roomAfter, isNotNull,
|
||||
reason: 'Testraum nach Migration nicht mehr in der DB');
|
||||
// Aufräumen (Session serverseitig beenden).
|
||||
await _logoutWithoutStraySync(client);
|
||||
await logoutWithoutStraySync(client); // App-Baustein (session_logout.dart)
|
||||
await client.dispose(closeDatabase: true);
|
||||
},
|
||||
skip: skip,
|
||||
|
||||
Reference in New Issue
Block a user