feat(ateapi): track actor_template_uid per snapshot on ExternalSnapshot - #1713
shrutiyam-glitch wants to merge 8 commits into
Conversation
Add actor_template_uid to ExternalSnapshot and LocalSnapshotInfo so each snapshot records the UID of the ActorTemplate whose sandbox its guest state was captured from. A paused actor can hold a local checkpoint and an external snapshot captured under different templates after a template repoint, so template provenance must be tracked per snapshot rather than relying solely on ActorStatus.current_actor_template_uid.
Stamp ExternalSnapshot.actor_template_uid and LocalSnapshotInfo.actor_template_uid with the active sandbox's ActorTemplate UID when suspending or pausing an actor, and when creating an actor from a tag.
Compare targetTemplateUID against LocalSnapshotInfo.actor_template_uid for local checkpoint restores and against ExternalSnapshot.actor_template_uid for external snapshot restores. This ensures resuming a paused actor whose local checkpoint matches the target template restores in FULL even when an older external snapshot on the actor came from a previous template.
Extend TestUpdateTemplateLifecycle to assert external_snapshot.actor_template_uid after suspend, and add a pause-then-resume sequence under template B while the actor still holds template A's external snapshot to verify local checkpoint provenance preserves memory state on FULL restores.
8d7186a to
9d88892
Compare
CreateActor now stamps the resolved template UID onto the golden ExternalSnapshot it seeds, so the functional test expectations for create, update, resume, and pause must carry it too.
| } | ||
|
|
||
| // | ||
| // Pause under template B while the external snapshot is still from |
There was a problem hiding this comment.
// Pause under template B while the external snapshot is still from
// template A: LocalSnapshotInfo records template B while ExternalSnapshot
// retains template A.
Is that true? After pause, the ExternalSnapshot entry should be cleared from the Actor.
There was a problem hiding this comment.
ensurePausedFinalized sets LocalSnapshotInfo and clears WorkerAssignment, leaving ExternalSnapshot intact.
| // captured under a template other than the actor's current one. They are | ||
| // tracked separately because the two can have been captured under | ||
| // different templates, and each restore path reads only its own. | ||
| LocalTemplateReplaced bool |
There was a problem hiding this comment.
LocalTemplateReplaced should not be possible, updating an actor template is only allowed for suspended actors, this might be an existing bug.
There was a problem hiding this comment.
my bad, I went through the flow again, updating an actor's template is only possible in suspended state.
whenever an actor resumes from a local pause checkpoint (LocalSnapshotInfo != nil), its template could not have been changed via UpdateActor since the pause checkpoint was taken. So LocalTemplateReplaced is not required, removed and update the title and pr desc.
…calSnapshotInfo.actor_template_uid
Follow up on the comment - #1675 (comment)
Stamps
actor_template_uidontoExternalSnapshotso template provenance travels with the snapshot itself, rather than being inferred from the singleActorStatus.current_actor_template_uid.Motivation
current_actor_template_uidrecords the template the last sprint booted with (finalizeRunningstamps it on every resume). It does not record the template the snapshot was captured under. Those two diverge as soon as an actor runs a sprint that does not produce a new durable snapshot, andloadActorForResumewas using the former to decide whether to force aDATA-only restore instead ofFULL.Walking an actor through a repoint and a crash:
current_…_uidExternalSnapshotUpdateActorrepoints the spec to BA != B, restoresDATA, sprint boots on Bcurrent == target == B, so no repoint is detectedAt step e the old check reports "template not replaced" and restores the external snapshot in
FULL— replaying a memory image captured under A's sandbox on B. That is exactly the case the guard exists to prevent; it was silently defeated by the sprint at step c advancingcurrent_actor_template_uidpast the snapshot.(Note: Paused actors do not face this divergence. Because
UpdateActoris only allowed in theSUSPENDEDstate, a paused actor cannot have its template updated. Therefore, local checkpoints do not need separate template provenance tracking).Changes
actor_template_uidfield toExternalSnapshot.ActorTemplateUID when suspending an actor or creating an actor from a tag.ExternalSnapshot.actor_template_uid) rather than the actor's overall status. Local restores bypass this check entirely since templates cannot change during a pause.Tests
TestResumeActor_AteletWireRequest(unit): snapshot fixtures now carryactor_template_uid, since provenance is read from the snapshot rather than from actor status.TestUpdateTemplateLifecycle(e2e): assertsexternal_snapshot.actor_template_uidafter suspend and re-suspend.A
TODOmarks theresume → crash/revert → resumee2e sequence to be added onceRevertActorlands — that is the path described in the table above.