Skip to content

SuspendActor returns a suspended actor as it is, and atelet uploads a paused actor's snapshot in the background - #2804

Merged
Michelle Au (msau42) merged 5 commits into
agent-substrate:mainfrom
zoez7:remove-paused-to-suspended
Oct 17, 2026
Merged

Michelle Au (msau42) merged 5 commits into
agent-substrate:mainfrom
zoez7:remove-paused-to-suspended

Conversation

@zoez7

@zoez7 Zoe Zhao (zoez7) commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

SUSPENDED is now a single state. SuspendActor returns a SUSPENDED actor as is. It no longer uploads a paused actor's node-local snapshot through atelet's PromoteSnapshot. atelet uploads the snapshot in the background.

  • Both suspend modes record a pending durable copy of the snapshot.
  • Tagging an actor whose latest snapshot is not uploaded yet still fails. The error message no longer suggests suspending it.

Breaking change

A synchronous SuspendActor on a paused actor no longer waits for the snapshot upload. It returns the actor right away. Callers that need the durable copy should wait for the snapshot's durable copy to complete.

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

A sync SuspendActor of a paused actor used to upload its node-local
snapshot through atelet's PromoteSnapshot. SUSPENDED is now a single
state: SuspendActor returns a SUSPENDED actor as it is, whatever the
requested mode, and never promotes a node-local snapshot. atelet uploads
it in the background, and the detach report unpins the actor from the
node.

A suspend now records a pending durable copy of its snapshot in either
mode, so both modes leave the same in-progress shape and a retry can
switch modes: the request's mode only picks the upload mode and how
finalize records the snapshot.

HostingNode treats a SUSPENDED actor as hosted on its assigned node while
any of its snapshots is still there, whether or not it was uploaded.
Tagging an actor whose latest snapshot is not uploaded yet still fails,
now with a message that no longer suggests suspending it.

Update the tests for SuspendActor returning a SUSPENDED actor as it is
and for both modes marking a snapshot with a pending durable copy.

- Table tests pin that SuspendActor, in either mode, leaves every
  SUSPENDED shape untouched (paused, upload pending, uploaded, durable,
  no snapshot), that a re-entered suspend keeps the persisted snapshot
  location whatever mode the retry asks for, and the state matrix for
  both modes.
- In-progress fixtures use the new mark: a PENDING durable copy with no
  locality yet.
- HostingNode tests, including the credential minting ones, follow the
  new rule: a SUSPENDED actor is hosted by its assigned node while any of
  its snapshots is still there.
- Tests of the promote path, the paused-origin discriminator, and the
  pending-local helper are removed, as are the e2e cases that suspended
  a paused actor to upload its snapshot.

Update the docs to match:

- architecture.md: drop the SUSPENDED -> SUSPENDING edge, and describe a
  paused actor's snapshot as node-local with a PENDING durable copy that
  atelet uploads, then detaches from the node.
- api-guide.md: document SuspendOptions.mode and the SUSPENDED case, and
  say a paused actor's node pin ends when atelet detaches it.
- glossary.md: Suspend applies to a running Actor; Pause is the
  asynchronous suspend.
Every suspend now records the upload URI when it marks the snapshot, so a
pause's snapshot always carries a PENDING durable copy. Remove the code
that built the URI for a pause that recorded none: pauseURIFunc, the
unrecorded branch of applyLatestDurable, the template lookup in
ApplyReportedSnapshotState, and the actorTemplate parameter of
ensureSuspendedFinalized. A reported upload of a snapshot that records no
durable copy is now refused.

Run the golden-actor check in MarkSuspending after the state check and
before the SUSPENDING skip, so an async suspend of a golden actor in a
state no suspend takes reports that state, and an async retry of a golden
actor's suspend is refused instead of finishing as a pause.

UpdateActor's template-change error and the canRelaxRuntime comment no
longer suggest suspending a paused actor: its node pin ends once atelet
uploads the snapshot and detaches it from the node.

Tests:
- newLocalSnapshot moves out of production code to newPausedSnapshot, a
  test helper that builds the real shape: a locality plus a PENDING
  durable copy, or the in-progress mark when there is no locality.
- Cases seeding a paused snapshot with no durable copy are dropped or
  moved to the real shape.
- TestSuspendActorAsynchronous expects the PENDING durable copy.
- TestResumeActor_RelocatesAfterSuspendFromPaused becomes
  TestResumeActor_RelocatesAfterDetach: the pin ends on atelet's detach
  report, not on a suspend.
- A table test pins the golden check's order.
Comment thread pkg/proto/ateapipb/ateapi.proto Resolved
…e copy on pause

A pause now records a PENDING durable copy of its snapshot, so an actor
that resumes before atelet reports the upload and is then reverted can
hold more than one PENDING durable snapshot. Revert deleted only the
latest one, leaving the earlier pause's objects in storage until the
actor was deleted. ensureInProgressSnapshotDiscarded now deletes every
PENDING durable snapshot, which the revert drops from the record anyway.
It checks that the actor owns every URI before deleting any, so a
corrupted record deletes nothing.

FinalizeSuspended now crashes an async suspend whose latest snapshot has
no durable copy, as it already did for a sync one. Without it, atelet's
background upload of the snapshot could never be recorded.

Update the durable_snapshot proto comment: a pause's snapshot that only
exists on its node still carries a PENDING durable copy.
…spended

# Conflicts:
#	internal/e2e/suites/demo/demo_test.go
@msau42
Michelle Au (msau42) added this pull request to the merge queue Oct 17, 2026
Merged via the queue into agent-substrate:main with commit 905745d Oct 17, 2026
15 checks passed
@zoez7
Zoe Zhao (zoez7) deleted the remove-paused-to-suspended branch October 17, 2026 21:25
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