Repository navigation
ateapi accepts snapshot report from atelet for actors in CRASHED state - #3148
Dmitry Berkovich (dberkov) merged 3 commits into
Conversation
27db651 to
358ff93
Compare
| case ateapi.ActorState_ACTOR_STATE_CRASHED: | ||
| return apierror.FailedPrecondition("actor %s is %s; revert it first", actorRef, st) | ||
| reported := state.GetLatestDurable() | ||
| snap := findSnapshotByGeneration(status.GetSnapshots(), reported.GetGeneration()) | ||
| // A crashed Actor keeps its AssignedNode, so only Locality tells a crashed | ||
| // suspend's snapshot from an upload that finished on node: only a finalized | ||
| // suspend sets Locality. Its upload is not recorded, and a revert deletes | ||
| // it with the rest of the discarded execution. | ||
| if snap != nil && snap.GetLocality() == "" && snap.GetDurableSnapshot().GetStatus() != ateapi.SnapshotStorageStatus_SNAPSHOT_STORAGE_STATUS_COMPLETED { | ||
| slog.InfoContext(leaseCtx, msgDurableCrashedSuspend, | ||
| slog.Int("generation", int(reported.GetGeneration())), | ||
| slog.String("uuid", reported.GetUuid())) | ||
| } else if err := applyLatestDurable(leaseCtx, status, reported); err != nil { | ||
| return err | ||
| } | ||
| if state.GetLatestLocal() == nil && state.GetUploading() == nil { | ||
| if err := applyDetach(status, node, reported.GetGeneration()); err != nil { | ||
| return err | ||
| } | ||
| } |
There was a problem hiding this comment.
🤖 Because the snap != nil && snap.GetLocality() == "" && ... check runs before applyLatestDurable, a report naming a crashed suspend's generation bypasses the UUID, DurableSnapshot != nil, upload URI, and fidelity validations in applyLatestDurable. If such a report also has LatestLocal == nil && Uploading == nil with a mismatched UUID or wrong upload URI, ApplyReportedSnapshotState will log msgDurableCrashedSuspend and apply the detach to older snapshots instead of rejecting the report.
If we move this check into applyLatestDurable right after the validation checks (before setting snap.Fidelity and snap.DurableSnapshot.Status):
if status.GetState() == ateapi.ActorState_ACTOR_STATE_CRASHED && snap.GetLocality() == "" {
slog.InfoContext(ctx, msgDurableCrashedSuspend,
slog.Int("generation", int(reported.GetGeneration())),
slog.String("uuid", reported.GetUuid()))
return nil
}then all validations still run (snap is already guaranteed not to be COMPLETED at that point in applyLatestDurable), and ACTOR_STATE_CRASHED can share applyActorSnapshotState with SUSPENDED and RUNNING without duplicating it here.
| msgDurableNotRecorded = "Ignoring a durable snapshot at a generation the actor no longer records" | ||
| msgDurableOlder = "Ignoring a durable snapshot older than the latest completed one" | ||
| msgDurableNotRecorded = "Ignoring a durable snapshot at a generation the actor no longer records" | ||
| msgDurableCrashedSuspend = "Ignoring the upload of a snapshot whose suspend crashed" |
There was a problem hiding this comment.
🤖 Nit: msgDurableCrashedSuspend is defined alongside msgDurableOlder and msgDurableNotRecorded, which are tested in TestApplyLatestDurableLogsStaleReports. If the crashed-suspend check is moved into applyLatestDurable, we can also add a test case for msgDurableCrashedSuspend in TestApplyLatestDurableLogsStaleReports.
A report for a CRASHED actor failed with FailedPrecondition, which atelet does not retry. A revert then deleted an upload that atelet had finished as in progress. A report for a CRASHED actor now records its finished upload and applies a detach. A crashed suspend's snapshot has no Locality, so its upload is not recorded and the revert deletes it. The detach does not require the latest snapshot on the node to be durable, because a revert drops local snapshots before the actor can resume.
ReportActorSnapshotState also accepted a report from a node that held one of the actor's snapshots while the actor was placed elsewhere. A snapshot's locality is set only to the assigned node, and the actor leaves a node only after its snapshots there are detached.
358ff93 to
4a0dcc9
Compare
A report naming a crashed suspend's snapshot skipped the uuid, upload URI and fidelity checks in applyLatestDurable. Move the check into applyLatestDurable after those checks, so a CRASHED actor goes through applyActorSnapshotState like a SUSPENDED or RUNNING one. Check the actor's state before cloning it.
4a0dcc9 to
d083fd3
Compare
Why is this needed?
actorOnNodecheck to only check the assigned node. Today, each actor's local snapshots are cleared during Detach, we don't have any actors with old snapshots on a different node.AI use: AI-assisted, I reviewed and tested it.