From f80c65b08ee42945dceae487fe45c996c37c4076 Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Thu, 11 May 2023 09:56:20 +0300 Subject: [PATCH] Sync replica snapshots to previous If Litestream is restarted often with high snapshot interval it's possible for it to skip multiple snapshots in a row causing long restore times and inconsistent storage patterns. --- replica.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/replica.go b/replica.go index 876e71d6..9d661ea3 100644 --- a/replica.go +++ b/replica.go @@ -731,6 +731,30 @@ func (r *Replica) snapshotter(ctx context.Context) { return } + if pos, err := r.db.Pos(); err != nil { + log.Printf("%s(%s): snapshotter cannot determine generation: %s", r.db.Path(), r.Name(), err) + } else if !pos.IsZero() { + if snapshot, err := r.maxSnapshot(ctx, pos.Generation); err != nil { + log.Printf("%s(%s): snapshotter cannot determine latest snapshot: %s", r.db.Path(), r.Name(), err) + } else if snapshot != nil { + nextSnapshot := r.SnapshotInterval - time.Since(snapshot.CreatedAt) + if nextSnapshot < 0 { + nextSnapshot = 0 + } + + log.Printf("%s(%s): previous snapshot created at %s, next in %s", r.db.Path(), r.Name(), snapshot.CreatedAt.Format(time.RFC3339), nextSnapshot.String()) + + select { + case <-ctx.Done(): + return + case <-time.After(nextSnapshot): + if _, err := r.Snapshot(ctx); err != nil && err != ErrNoGeneration { + log.Printf("%s(%s): snapshotter error: %s", r.db.Path(), r.Name(), err) + } + } + } + } + ticker := time.NewTicker(r.SnapshotInterval) defer ticker.Stop()