🐛 Fix sync from zero

This commit is contained in:
2026-08-20 17:35:43 +02:00
parent babc9a8096
commit 29284a024d
2 changed files with 9 additions and 6 deletions
+6 -3
View File
@@ -36,8 +36,9 @@ type SyncChange struct {
} }
// Pull returns all sync_log rows with version > sinceVersion. // Pull returns all sync_log rows with version > sinceVersion.
// It calls Prune first with a 30-day TTL. // It calls Prune first with a 30-day TTL. A zero-version pull is a bootstrap
// If the client is behind a prune marker it returns ErrSyncStale. // and may proceed past the prune marker; non-zero clients behind the marker
// must perform a full re-sync.
func (s *SyncStore) Pull(ctx context.Context, sinceVersion int64) ([]SyncChange, int64, error) { func (s *SyncStore) Pull(ctx context.Context, sinceVersion int64) ([]SyncChange, int64, error) {
if err := s.Prune(ctx, 30*24*time.Hour); err != nil { if err := s.Prune(ctx, 30*24*time.Hour); err != nil {
return nil, 0, err return nil, 0, err
@@ -58,10 +59,12 @@ func (s *SyncStore) Pull(ctx context.Context, sinceVersion int64) ([]SyncChange,
if err := rows.Scan(&c.Entity, &c.EntityID, &c.Op, &c.Version, &c.Payload); err != nil { if err := rows.Scan(&c.Entity, &c.EntityID, &c.Op, &c.Version, &c.Payload); err != nil {
return nil, 0, err return nil, 0, err
} }
// First row with entity="_pruned" means client is stale.
if c.Entity == pruneEntity { if c.Entity == pruneEntity {
if sinceVersion != 0 {
return nil, 0, ErrSyncStale return nil, 0, ErrSyncStale
} }
continue
}
if c.Version > maxVersion { if c.Version > maxVersion {
maxVersion = c.Version maxVersion = c.Version
} }
+2 -2
View File
@@ -76,8 +76,8 @@ func TestSyncPruneStaleClient(t *testing.T) {
t.Fatalf("Prune: %v", err) t.Fatalf("Prune: %v", err)
} }
// A stale client (since=0) should get ErrSyncStale. // A client with an existing sync position behind the marker is stale.
_, _, err := s.Pull(ctx, 0) _, _, err := s.Pull(ctx, 1)
if !errors.Is(err, store.ErrSyncStale) { if !errors.Is(err, store.ErrSyncStale) {
t.Fatalf("expected ErrSyncStale, got %v", err) t.Fatalf("expected ErrSyncStale, got %v", err)
} }