Beschreibung
Bei einer einzelnen gemerkten Reise ist bei mir ein inkonsistenter Zustand entstanden:
- Die Reise ist weiterhin im Tab „Reisen“ sichtbar.
- Beim Öffnen der Reise zeigt das Lesezeichen oben rechts aber an, dass sie nicht gemerkt sei.
- Dadurch kann ich sie nicht normal „entmerken“.
- Wenn ich sie erneut merke und danach wieder entmerke, verschwindet der ursprüngliche Eintrag nicht.
- Inzwischen wird die Reise sogar mehrfach im Reisen-Tab angezeigt.
Möglicherweise hängt das mit folgendem vorherigen Ereignis zusammen:
Ich habe einmal versehentlich eine Reise im Reisen-Tab per Swipe gelöscht. In der Schnelle konnte ich nicht erkennen, welche Reise das war. Als ich danach nach einer fehlenden Reise gesucht habe, schien keine zu fehlen.
Daher mein Verdacht: Durch den Swipe wurde eine Reise möglicherweise nur lokal gelöscht, blieb aber DB-seitig weiterhin als „Gemerkte Reise“ bestehen.
Das Problem tritt bei mir derzeit nur bei einer Reise auf, was zu diesem Ablauf passen würde.
Beobachtetes Verhalten
Sinngemäß:
- Reise wird im Reisen-Tab angezeigt.
- Reise öffnen.
- Lesezeichen oben rechts ist leer.
- Erneut auf Lesezeichen tippen.
- Reise wird erneut gemerkt.
- Wieder entmerken.
- Ursprünglicher Eintrag bleibt bestehen.
- Nach mehreren Versuchen existiert die Reise mehrfach im Reisen-Tab.
Erwartetes Verhalten
Eine im Reisen-Tab als „gemerkt“ angezeigte Reise sollte:
- beim Öffnen auch ein aktives Lesezeichen zeigen
- sich über das Lesezeichen zuverlässig entmerken lassen
- beim Swipe vollständig entfernt werden
- nicht mehrfach angelegt werden können
Lokaler Zustand und DB-seitige „Meine Reisen“ sollten konsistent bleiben.
Mögliche Ursache im aktuellen Code
Soweit ich den Code richtig verstehe, zeigt der Reisen-Tab zeigt bei eingeloggtem DB-Konto zwei unabhängige Quellen gleichzeitig:
- DB-seitige „Gemerkte Reisen“ aus
savedReisenProvider
- lokal gespeicherte Reisen aus
libraryProvider
Das sieht man direkt im Reisen-Screen: erst werden die serverseitigen „Gemerkten Reisen“ gerendert, danach separat die lokalen „Anstehenden Reisen“.
Der Swipe löscht aber nur lokal
Beim Wegwischen einer lokalen Reise passiert ausschließlich:
onDismissed: (_) {
ref.read(libraryProvider.notifier).removeJourney(saved.key);
}
Und removeJourney() entfernt nur aus state.journeys und speichert die lokale Liste neu:
void removeJourney(String key) {
state = state.copyWith(
journeys: state.journeys.where((j) => j.key != key).toList());
_saveJourneys();
}
Es gibt dort keinerlei Löschung der DB-seitigen gemerkten Reise.
Das heißt: Ein Lösch-Swipe kann tatsächlich exakt Folgendes erzeugt haben:
lokal gelöscht
aber auf dem DB-Konto weiterhin gemerkt
Also "halb gelöscht".
Warum das Lesezeichen danach leer ist
Ob das Lesezeichen oben rechts gefüllt erscheint, wird ausschließlich anhand der lokalen Library geprüft:
final key =
SavedJourney(journey: journey, savedAtMs: 0).key;
final saved = ref.watch(libraryProvider).hasJourney(key);
hasJourney() schaut wiederum nur in:
journeys.any((j) => j.key == key)
Die App fragt an dieser Stelle nicht, ob dieselbe Reise noch DB-seitig als „gemerkt“ existiert.
Damit ergibt das Verhalten vollkommen Sinn:
- Reise ursprünglich gemerkt
- lokal und DB-seitig vorhanden
- Swipe im Reisen-Tab
- lokale Reise gelöscht
- DB-Reise bleibt bestehen
- sie erscheint weiterhin unter „Gemerkte Reisen“
- beim Öffnen ist das Lesezeichen leer, weil lokal nichts mehr existiert
Und warum Duplikate kommen
Das ist der nächste kritische Teil.
Wenn man bei leerem Lesezeichen erneut auf „merken“ tippt:
wird wieder ein lokaler Eintrag angelegt.
Wenn man eingeloggt bist, wird anschließend zusätzlich _syncDbReise(..., saved: true) aufgerufen. Diese Funktion legt über saveReise() eine neue DB-seitige gemerkte Reise an:
final rkUuid = await service.saveReise(...);
if (rkUuid != null) ids.put(key, rkUuid);
Wenn die alte DB-Reise noch existiert, entsteht also:
alte serverseitige Reise
- neu angelegte serverseitige Reise
Genau dadurch können doppelte Einträge im Reisen-Tab entstehen.
Noch ein zusätzliches Problem
Die Zuordnung:
lokaler Journey-Key → DB-rkUuid
wird nur im Arbeitsspeicher der laufenden Sitzung gehalten:
class DbSavedReiseIds extends Notifier<Map<String, String>> {
Map<String, String> build() => {};
}
Der Kommentar behauptet zwar:
cross-session removal reconciles via the trip overview
aber im von mir geprüften Code sehe ich für diese Zuordnung keine tatsächliche persistente Speicherung und auch keine erkennbare Rekonstruktion aus der Übersicht. Die Map startet leer.
Beim Entmerken wird die DB-Reise aber nur gelöscht, wenn für den lokalen Key eine rkUuid in genau dieser Map gefunden wird:
final rkUuid = ids.take(key);
if (rkUuid != null) await service.deleteReise(rkUuid);
Das heißt: Nach App-Neustart oder bei einer serverseitigen Reise, die nicht in dieser Sitzung über genau diesen Bookmark-Flow angelegt wurde, kann das Entmerken lokal funktionieren, ohne die passende DB-Reise zu löschen.
Das ist meines Erachtens ein ziemlich klarer Synchronisationsbug.
Beschreibung
Bei einer einzelnen gemerkten Reise ist bei mir ein inkonsistenter Zustand entstanden:
Möglicherweise hängt das mit folgendem vorherigen Ereignis zusammen:
Ich habe einmal versehentlich eine Reise im Reisen-Tab per Swipe gelöscht. In der Schnelle konnte ich nicht erkennen, welche Reise das war. Als ich danach nach einer fehlenden Reise gesucht habe, schien keine zu fehlen.
Daher mein Verdacht: Durch den Swipe wurde eine Reise möglicherweise nur lokal gelöscht, blieb aber DB-seitig weiterhin als „Gemerkte Reise“ bestehen.
Das Problem tritt bei mir derzeit nur bei einer Reise auf, was zu diesem Ablauf passen würde.
Beobachtetes Verhalten
Sinngemäß:
Erwartetes Verhalten
Eine im Reisen-Tab als „gemerkt“ angezeigte Reise sollte:
Lokaler Zustand und DB-seitige „Meine Reisen“ sollten konsistent bleiben.
Mögliche Ursache im aktuellen Code
Soweit ich den Code richtig verstehe, zeigt der Reisen-Tab zeigt bei eingeloggtem DB-Konto zwei unabhängige Quellen gleichzeitig:
savedReisenProviderlibraryProviderDas sieht man direkt im Reisen-Screen: erst werden die serverseitigen „Gemerkten Reisen“ gerendert, danach separat die lokalen „Anstehenden Reisen“.
Der Swipe löscht aber nur lokal
Beim Wegwischen einer lokalen Reise passiert ausschließlich:
Und
removeJourney()entfernt nur ausstate.journeysund speichert die lokale Liste neu:Es gibt dort keinerlei Löschung der DB-seitigen gemerkten Reise.
Das heißt: Ein Lösch-Swipe kann tatsächlich exakt Folgendes erzeugt haben:
Also "halb gelöscht".
Warum das Lesezeichen danach leer ist
Ob das Lesezeichen oben rechts gefüllt erscheint, wird ausschließlich anhand der lokalen Library geprüft:
hasJourney()schaut wiederum nur in:Die App fragt an dieser Stelle nicht, ob dieselbe Reise noch DB-seitig als „gemerkt“ existiert.
Damit ergibt das Verhalten vollkommen Sinn:
Und warum Duplikate kommen
Das ist der nächste kritische Teil.
Wenn man bei leerem Lesezeichen erneut auf „merken“ tippt:
toggleJourney(journey);wird wieder ein lokaler Eintrag angelegt.
Wenn man eingeloggt bist, wird anschließend zusätzlich
_syncDbReise(..., saved: true)aufgerufen. Diese Funktion legt übersaveReise()eine neue DB-seitige gemerkte Reise an:Wenn die alte DB-Reise noch existiert, entsteht also:
Genau dadurch können doppelte Einträge im Reisen-Tab entstehen.
Noch ein zusätzliches Problem
Die Zuordnung:
wird nur im Arbeitsspeicher der laufenden Sitzung gehalten:
Der Kommentar behauptet zwar:
aber im von mir geprüften Code sehe ich für diese Zuordnung keine tatsächliche persistente Speicherung und auch keine erkennbare Rekonstruktion aus der Übersicht. Die Map startet leer.
Beim Entmerken wird die DB-Reise aber nur gelöscht, wenn für den lokalen Key eine
rkUuidin genau dieser Map gefunden wird:Das heißt: Nach App-Neustart oder bei einer serverseitigen Reise, die nicht in dieser Sitzung über genau diesen Bookmark-Flow angelegt wurde, kann das Entmerken lokal funktionieren, ohne die passende DB-Reise zu löschen.
Das ist meines Erachtens ein ziemlich klarer Synchronisationsbug.