carlos / platform Public

lease: Replicator.Close can return nil having flushed nothing; a failed flush still ends in hibernation open

Found by Astra's review of the flush-only replication class (feat/carloku-flush-only-class-20261002, report CODEX-FINDINGS-flush-only-class-review1.md, finding 1, P1). It is inherited: it affects every replication class on main, not the new one.

  1. internal/lease/lease.go Replicator.Close calls r.db.SyncAndWait(ctx) and drops its error, on the reasoning that the store's own final sync is the one that counts. But litestream's DB.Close runs its final syncs only for an initialised database (third_party/litestream/db.go, if db.db != nil). If SyncAndWait failed during initialisation (a drain right after a wake, before the first monitor tick, with the remote position lookup failing), db.db is nil, both final syncs are skipped, and Close returns nil with nothing uploaded.
  1. Separately, when Close does return an error, the activator's stop path records the outcome as uncertain, deletes the entry and logs the instance as hibernated. Losing the host afterwards loses the unflushed writes of an instance that reads as asleep.

Smallest fix for 1 (proposed, not built): keep SyncAndWait's error and return it when the store's Close did not itself complete a final sync. For 2: a failed checkpoint state with a retry, rather than reporting hibernation; that is a design change to the stop path.

Not fixed on the flush-only branch: it is the stop path of every hibernating instance and needs its own reviewed change.