fix: eigener Push ließ Client seinen Pull-Cursor über fremde Ereignisse springen
SyncEngine.PushAsync setzte den lokalen Pull-Cursor bisher aus PushResponse.ServerSequenceNr - dem globalen Zähler über alle Geräte nach dem eigenen Push, nicht dem tatsächlich zugestellten Stand. War beim Server zu diesem Zeitpunkt bereits ein noch nicht abgeholtes Ereignis eines anderen Geräts mit niedrigerer ServerSeq vorhanden, sprang der Cursor darüber hinweg und der direkt folgende Pull bekam 0 Ereignisse, ohne es je angewendet zu haben - ein zweiter, unabhängiger Cursor-Bug mit demselben Symptom wie der vorherige Wasserzeichen-Fix, diesmal client- statt serverseitig. Ergänzt außerdem einen "Vollständigen Sync erzwingen"-Button in den Sync-Einstellungen, damit bereits durch diesen Bug zu weit vorgerückte Geräte ihren Fortschritt manuell zurücksetzen und alle Ereignisse erneut laden können. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -95,9 +95,19 @@ public class SyncEngine : IDisposable
|
||||
foreach (var evt in pending)
|
||||
if (result.AssignedServerSeqs.TryGetValue(evt.EventId, out var seq))
|
||||
_queue.SetKnownServerSeq(evt.EntityType, evt.EntityId, seq);
|
||||
_queue.SetLastServerSeq(result.ServerSequenceNr);
|
||||
_logger?.Info($"Sync: Push - vom Server bestätigt bis ServerSequenceNr={result.ServerSequenceNr}, " +
|
||||
$"{result.ConflictingEventIds.Count} vom Server abgelehnt (Konflikt).");
|
||||
// ANDERS ALS FRÜHER wird der lokale Pull-Cursor (_queue.SetLastServerSeq) hier NICHT aus
|
||||
// result.ServerSequenceNr gesetzt: das ist der GLOBALE Zähler über ALLE Geräte NACH diesem
|
||||
// Push, nicht der Stand, den DIESES Gerät tatsächlich per Pull erhalten hat. Hatte der
|
||||
// Server zu diesem Zeitpunkt bereits ein noch nicht abgeholtes Ereignis eines ANDEREN
|
||||
// Geräts mit niedrigerer ServerSeq, würde der Cursor hier darüber hinwegspringen - der
|
||||
// direkt anschließende PullAsync würde dann schon mit einem "since" danach fragen und 0
|
||||
// Ereignisse zurückbekommen, ohne das fremde Ereignis je angewendet zu haben (exakt das
|
||||
// Symptom, das die Ereignis-Anzahl-Korrektur in EventStore.Pull eigentlich beheben sollte -
|
||||
// hier aber über einen anderen Pfad wieder hereinkam). PullAsync pflegt den Cursor bereits
|
||||
// korrekt selbst, ausschließlich anhand tatsächlich zugestellter Ereignisse.
|
||||
_logger?.Info($"Sync: Push - {pending.Count - result.ConflictingEventIds.Count} vom Server " +
|
||||
$"angenommen (aktueller globaler Stand ServerSequenceNr={result.ServerSequenceNr}), " +
|
||||
$"{result.ConflictingEventIds.Count} abgelehnt (Konflikt).");
|
||||
if (result.ConflictingEventIds.Count > 0)
|
||||
await HandleRejectedAsync(pending.Where(e => result.ConflictingEventIds.Contains(e.EventId)));
|
||||
return (pending.Count - result.ConflictingEventIds.Count,
|
||||
|
||||
Reference in New Issue
Block a user