Skip to content

atelet: Reject stale snapshot generations - #2803

Merged
Zoe Zhao (zoez7) merged 1 commit into
agent-substrate:mainfrom
msau42:snapshot-generation
Oct 17, 2026
Merged

Zoe Zhao (zoez7) merged 1 commit into
agent-substrate:mainfrom
msau42:snapshot-generation

Conversation

@msau42

@msau42 Michelle Au (msau42) commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Have Checkpoint and PromoteSnapshot reject a snapshot whose generation is below the actor's newest tracked snapshot on the node, or equal to it under a different snapshot UUID, with FailedPrecondition before doing any work.

Part of #2069

  • Tests pass
  • Appropriate changes to documentation are included in the PR

defer t.unlock(actorUID)
a, err := t.waitForDetachLocked(ctx, actorUID)
a, err := t.waitForDetachLocked(ctx, actorUID, func(a *actorSnapshots) error {
return a.checkGeneration(snap)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 question 🟢 – The removed TODO aimed for "no commit replaces a snapshot with an older one", but CommitLocal and CommitDurable still don't compare generations. Two Checkpoints of the same actor (say generations 5 and 6) can both pass this check, because holds don't exclude each other and newest() doesn't see an in-flight Checkpoint's target. If generation 5 commits last, LatestLocal and LatestDurable roll back to it, and the prune then deletes generation 6's local directory. Is a concurrent Checkpoint of one actor ruled out elsewhere? If not, CommitLocal and CommitDurable could skip a snapshot older than what they hold, as CommitPromoted now does.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. ateapi holds the actor lease during Checkpoint, but if a lease expires or a request times out while an earlier Checkpoint is still running on atelet, a newer one can arrive and overlap.

Updated both entry and commit to handle that:

  • BeginCheckpoint and BeginPromote now record their snapshot on a.inFlight until end() runs, and newest() includes inFlight so an older generation cannot start while a newer one is running.
  • CommitLocal now skips snapshots when !a.localNeeded(snap) and CommitDurable skips when !a.uploadNeeded(snap), so a stalled older checkpoint finishing after a newer commit leaves LatestLocal and LatestDurable alone (and PruneLocalCheckpoints keeps the newer local directory).

Have Checkpoint and PromoteSnapshot reject a snapshot whose generation
is below the actor's newest tracked snapshot on the node, or equal to it
under a different snapshot UUID, with FailedPrecondition before doing
any work. Commits also skip snapshots superseded while a checkpoint or
promote ran.
@zoez7
Zoe Zhao (zoez7) added this pull request to the merge queue Oct 17, 2026
Merged via the queue into agent-substrate:main with commit bdc2c3d Oct 17, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants