Some checks failed
CI / Rustfmt (push) Successful in 21s
CI / Cargo Audit & Deny (push) Successful in 32s
CI / Web Blocking Checks (push) Successful in 50s
CI / Security Blocking Checks (push) Successful in 9s
CI / Clippy (push) Failing after 1m58s
CI / Web Advisory Checks (push) Successful in 34s
CI / Security Advisory Checks (push) Successful in 1m26s
CI / Tests (push) Successful in 8m47s
3.1 KiB
3.1 KiB
Work Summary: Workflow Cancellation Policy
Date: 2026-03-09
Overview
Added configurable cancellation behavior for workflows. When a workflow is cancelled, the policy controls whether currently running tasks are allowed to finish (default) or are forcefully terminated via SIGTERM.
Changes
Backend (Rust)
crates/common/src/workflow/parser.rs
- Added
CancellationPolicyenum with two variants:AllowFinish(default) andCancelRunning - Added
cancellation_policyfield toWorkflowDefinitionwith#[serde(default, skip_serializing_if)]for backward compatibility - Added 5 unit tests covering default behavior, explicit values, JSON round-trip, and deserialization of legacy definitions without the field
crates/common/src/workflow/mod.rs
- Re-exported
CancellationPolicyfrom the workflow module
crates/api/src/routes/executions.rs
- Added
resolve_cancellation_policy()helper that loads the workflow definition from DB and extracts the policy (falls back toAllowFinishon any failure) - Refactored
cancel_workflow_children()to resolve the policy and delegate tocancel_workflow_children_with_policy() cancel_workflow_children_with_policy()respects the policy:AllowFinish: Only cancels pre-running children (Requested/Scheduling/Scheduled). Running children are left alone to complete naturally.advance_workflowsees the cancelledworkflow_executionand stops dispatching new tasks.CancelRunning: Cancels all children including running ones via SIGINT→SIGTERM→SIGKILL MQ messages to workers (previous hard-coded behavior).
- Policy is inherited through recursive cancellation of nested workflows
Frontend (TypeScript/React)
web/src/types/workflow.ts
- Added
CancellationPolicytype andCANCELLATION_POLICY_LABELSconstant - Added
cancellationPolicyfield toWorkflowBuilderState - Added
cancellation_policyfield toWorkflowYamlDefinitionandWorkflowGraphDefinition - Updated
builderStateToDefinition()andbuilderStateToGraph()to include the field (omitted when default) - Updated
definitionToBuilderState()to read the field back
web/src/pages/actions/WorkflowBuilderPage.tsx
- Added
cancellationPolicytoINITIAL_STATE - Added a dropdown select in the metadata row for choosing the cancellation policy
- The setting persists into both the full definition and the raw YAML graph view
Design Decisions
- Default is
AllowFinish: This is the safest behavior — running tasks complete naturally, preventing data corruption from interrupted operations. - No migration needed: The field is stored inside the
workflow_definition.definitionJSONB column.#[serde(default)]handles existing definitions that lack the field. - Policy inherited by nested workflows: When a parent workflow is cancelled, its cancellation policy propagates to all descendant workflows rather than each resolving its own.
skip_serializing_if: The default value is omitted from serialized JSON to keep stored definitions compact and backward-compatible.
Testing
- 29/29 workflow parser tests pass (5 new)
- Zero warnings across entire Rust workspace
- Zero TypeScript errors