Repository navigation
Crash a paused actor on resume when its node is gone - #3010
Conversation
087562b to
dd76dd0
Compare
|
|
||
| // latestLocalNotDurable reports whether the actor's latest local snapshot has | ||
| // no completed durable copy. | ||
| func latestLocalNotDurable(actor *ateapipb.Actor) bool { |
There was a problem hiding this comment.
One edge case is: although the latest snapshot was not recorded as durable, atelet has uploaded the snapshots already (and failed to call ateapi to ReportActorSnapshotStatus)
Wdyt of optimistically try to resume the actor on a different node, atelet can try to download the snapshot object, if atelet gets a not found error, we then crash the actor.
Lines 1615 to 1639 in d04d280
There was a problem hiding this comment.
Agreed, this case is real. The manifest goes last, so a PENDING copy with a manifest is complete, and revert would delete it as abandoned. I'd like to do it as a follow-up PR, though. ate-api-server can't check for the manifest today, because ControlProvider only has CleanupSnapshot and CopySnapshot. So it needs either a new RPC there, or a resume that restores the PENDING copy and turns atelet's NotFound into this crash. Which would you prefer? Until then, this PR still beats an actor that's stuck forever. The crash keeps the PENDING record, so nothing is deleted until someone reverts.
There was a problem hiding this comment.
I think "a resume that restores the PENDING copy and turns atelet's NotFound into this crash" is simpler
|
some overlap with #3005? |
|
Thanks again igooch for reviewing #2486 and picking up the resume follow-up; I'm closing #3005 in favor of this one. One case from that work may be useful here: the latest upload can become |
|
Thanks, good catch. Folded into ada3183. Resume now reads the actor again after |
|
LGTM. Please fix the CI failures. |
A paused actor whose node was deleted before atelet uploaded its latest snapshot stayed pinned to that node. Every resume returned Unavailable, and nothing told the caller the snapshot was lost. When resume finds no atelet on the node and the Node object is gone, it now crashes the actor. Revert then returns it to its last completed durable snapshot. A node that still exists, or a failed Node lookup, keeps the current retry.
Resume crashed the actor on a deleted node whenever it could not detach without atelet. That also covered an actor with a crash record whose latest snapshot was durable, and recorded a false crash. Resume now checks that the latest local snapshot has no completed durable copy. Move the doc sentence to a ResumeActor errors bullet, note the capacity precondition, and qualify the detach error rule.
When the caller went away or the lease was lost while resume checked whether the node still exists, it returned Unavailable. It now returns the context error, as the DetachActor call below it already does. Note in the test that a SUSPENDED actor never carries a crash record.
An upload recorded while resume checked the Node could still crash the actor, since crashActor reloads it without rechecking durability. Resume now reads the actor again after the lookup. If its latest snapshot became durable, it detaches. Otherwise it crashes only the version it checked, and a concurrent write aborts the resume for a retry. The regression case is adapted from eren23's closed alternative.
crashActorVersion assigned to an err declared by the GetActor call that moved to crashActor. That only compiled because releaseWorker declared err as well. Declare it on the UpdateActor call instead.
07014ce to
44ac323
Compare
The docs no longer speak of paused actors. Say a suspended actor loses its local snapshot instead.
…strate#3094) Part of agent-substrate#2470, follow-up from [3010](agent-substrate#3010 (comment)). atelet can upload a suspended actor's latest local snapshot and die before it reports the upload. If the node is then deleted, the upload is complete but still recorded `PENDING`. Resume crashed the actor, and a revert then deleted the upload. Resume now releases the deleted node and restores the snapshot on another node. atelet there has no local copy, so it reads the upload. The manifest is written last, so a missing or partial upload returns `NOT_FOUND`. - `recordGoneNode` clears `assigned_node`. The snapshot keeps its old locality, so `snapshotToResume` still picks it. - A `NOT_FOUND` from that restore crashes the actor with the existing gone-node message. - `finalizeRunning` records the restored snapshot `COMPLETED` and clears its locality. - `canRelaxRuntime` lets the snapshot fall back to another runtime, as a durable snapshot can. No proto changes. Resume claims a worker before it knows the upload exists, so a missing upload costs one placement. A revert still deletes an unreported upload, so the snapshot is lost if its restore fails for another reason or the actor is reverted before it resumes. AI use: Claude Code helped write the change and tests. I reviewed them. - [ ] Tests pass - [x] Docs updated
#2883 lets resume forget an unreachable node when a paused actor's latest snapshot is durable. When that upload is still PENDING, the actor stays pinned. If the node was deleted, every resume returns
Unavailable, and nothing says the snapshot is lost.Now, when resume finds no atelet on the pinned node and
NodeGonereports the Node object deleted, it reads the actor again. If the upload was recorded during the lookup, it detaches as usual. Otherwise it crashes the actor. The crash keepsassigned_nodeand the PENDING snapshot.RevertActorthen skips the terminate, deletes the pending objects, and returns the actor to its last completed durable snapshot. A node that still exists, or a failed Node lookup, keeps the current retry.There are two known limits. The check runs only after resume finds room on another node, so with no room anywhere resume still returns
RESOURCE_EXHAUSTED. And a Node object deleted while the machine keeps running crashes the actor even though its checkpoint is still on that machine. That's the same trade #2486 makes.A PENDING copy may already be fully uploaded if atelet died before reporting it. Resume still crashes the actor, and revert deletes that copy. Recovering it needs ate-api-server to check for the manifest, which is a follow-up.
No proto changes.
ResumeActorcan now crash the actor and returnFAILED_PRECONDITIONin this case, anddocs/api-guide.mdsays so.Part of #2470
Supersedes #3005. Its "upload completes during lookup" regression case is adapted here.
AI use: Claude Code helped write the change and tests. I reviewed them.