filer.remote.sync: save the resume position when a subscription ends

A failed event ends the subscription with ErrResubscribe, and the retry
loop runs startup again, recomputing -timeAgo from a later now. The
periodic checkpoint only runs as events arrive, so a failure before the
first one could start the retry after the event it failed on. The resume
position is now saved whenever the subscription returns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris LuandClaude Opus 5.5 committed 2026-11-06 01:27:20 -08:00
1 parent f535fca8f6
commit 7be919ded1
3 files changed
+41 -2

No files matched your search

@@ -695,6 +695,27 @@ func TestResolveLastSyncOffsetReturnsTheErrorToTheRetryLoop(t *testing.T) {
}
}
// TestSaveResumeOffsetKeepsTheStartForTheRetry: a subscription that ends
// before its first checkpoint still records where it started, so the retry's
// -timeAgo, recomputed from a later now, cannot start after it.
func TestSaveResumeOffsetKeepsTheStartForTheRetry(t *testing.T) {
filerAddress, dialOption := startKvFiler(t)
const dir = "/buckets/x"
start := time.Now().Add(-time.Hour)
processor := NewMetadataProcessor(func(*filer_pb.SubscribeMetadataResponse) error { return nil }, 1, start.UnixNano())
saveResumeOffset(dialOption, filerAddress, dir, processor)
got, err := resolveLastSyncOffset(dir, time.Hour, func() (*filer_pb.Entry, error) { return nil, nil }, func() (int64, error) {
return remote_storage.GetSyncOffset(dialOption, filerAddress, dir)
})
if err != nil {
t.Fatal(err)
}
if got.After(start) {
t.Fatalf("the retry starts at %v, after the first subscription's start %v", got, start)
}
}
func TestRemoteUploadReaderSharesOneChunkCache(t *testing.T) {
entry := entryWith("blob.bin", nil, chunk("3,01", "e1"))
for i := 0; i < 3; i++ {