- Diagrams
- Flows
- Cancel Flow
Cancel Flow
Cancellation commits to the database first and signals NATS second, and that order is the whole design. A compare-and-swap on runs.version marks the run terminal, sets its cancellation cause and ended_at, and releases the scheduler claim. Only then is a message published to the CANCEL stream. Nothing in the repo subscribes to that stream today, so the signal is a hook for future consumers.
If that publish fails the run stays cancelled. Executors reconcile from the database, so the signal is an optimisation, not a prerequisite. A push executor never reads CANCEL at all — PushExecutor.Execute calls store.GetRun first and skips a run that is already terminal, and PushExecutor.isRunCancelled calls it again before each HTTP attempt, so a cancelled run stops at the next dispatch.
The publish carries a message ID (cancel-{runID}), so a repeated cancel does not duplicate the signal. Cancelling an already-terminal run is refused outright rather than treated as a no-op. The same path also runs cancel_on cleanup, records an audit event with the (truncated) reason, and publishes the lifecycle event to PUBSUB subscribers.