transition

open suspend override fun transition(id: JobId, from: JobState, to: JobState, fence: Long? = null, error: JobError? = null): Boolean

Compare-and-set state transition. See interface KDoc for fence semantics.

Stores enforce CAS only, never state-machine edge legality: whether to is a legal successor of from is the runtime's responsibility, mirroring a SQL UPDATE ... WHERE state = ? with no CHECK constraint on the target state.

fence is optional because callers that never claimed the job (a producer cancelling a Scheduled run) have no fence to pass. Transitions out of JobState.Running MUST carry the fence from the worker's ClaimedJob: omitting it there silently disables zombie-worker protection. On success, stores clear the lease and holder when to is terminal AND when to is JobState.Failed, which is not terminal but is no longer running. Stores stamp the terminal timestamp when to is terminal and CLEAR it when to is not: a requeued row is live again, and must neither read as terminal to queries nor inherit a stale timestamp on its next terminal transition.

error is why the attempt failed. When non-null, the store persists it as the row's last error in the same atomic write as the state change, replacing any previous record. When null, the stored error is left untouched: a requeue or a later success keeps the last failure readable through JobDetails.lastError, with its attempt number saying which run it belongs to. The runtime passes it on every transition to JobState.Failed and JobState.DeadLettered and nowhere else; stores store it and never interpret it.