Skip to content

Runtime-routed task transitions write without a compare-and-set #4532

Description

@lsm

A Space task transition that routes to the workflow runtime — park_stopped, recover_transition, stop_for_status — is not written atomically against the status the pipeline decided on.

decide returns the executor result directly for those routes, so writeStatus (and its expectedStatus / expectedWorkflowRunId compare-and-set) never runs. The only protection is snapshotStillCurrent() in transition-task.ts, a plain re-read of status and workflowRunId immediately before dispatch. The executors behind SpaceRuntimeService.parkStoppedWorkflowTask, stopWorkflowBackedTaskForStatus and recoverTaskExecution then read and update the task again with no expectation carried in.

So there is a window between that re-read and the executor's write. If another writer moves an in_progress task to blocked inside it, a cancellation aimed at in_progress still cancels — from blocked — and performs the workflow and session side effects, rather than rejecting.

This predates #4524 and is not caused by it. #4524 added an optional caller-supplied expectedStatus, which is a true compare-and-set on the direct-write path and a pre-dispatch check on these routes; its description says exactly that, so no caller is promised atomicity it does not get. Closing the window properly means threading the expected snapshot into each runtime executor's own transition, which touches three SpaceRuntimeService entry points and their call sites — a separate slice.

Worth deciding whether the guarantee should be uniform before more callers adopt expectedStatus. spaceTask.publish will be the first, and publish routes to a direct write (draft tasks have no active run), so it is unaffected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions