diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index 68f415e7cf69a..ec2e688871caa 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -475,6 +475,11 @@ where } } +#[derive(Deserialize)] +struct RawFlowFailureModule { + failure_module: Option>, +} + #[instrument(level = "trace", skip_all)] pub async fn add_completed_job_error( db: &Pool, @@ -922,7 +927,17 @@ pub async fn add_completed_job< ) .await; } else if !skip_downstream_error_handlers - && matches!(queued_job.job_kind, JobKind::Flow | JobKind::Script) + && (matches!(queued_job.job_kind, JobKind::Script) + || matches!(queued_job.job_kind, JobKind::Flow) + && queued_job + .raw_flow + .as_ref() + .and_then(|v| { + serde_json::from_str::((**v).get()) + .ok() + .and_then(|v| v.failure_module) + }) + .is_none()) && queued_job.parent_job.is_none() { let result = serde_json::from_str( diff --git a/frontend/src/lib/components/FlowGraphViewer.svelte b/frontend/src/lib/components/FlowGraphViewer.svelte index afeb0438b1fc3..ec5f4523dc846 100644 --- a/frontend/src/lib/components/FlowGraphViewer.svelte +++ b/frontend/src/lib/components/FlowGraphViewer.svelte @@ -38,8 +38,14 @@ failureModule={flow?.value?.failure_module} preprocessorModule={flow?.value?.preprocessor_module} on:select={(e) => { - const mod = dfs(flow?.value?.modules ?? [], (m) => m).find((m) => m?.id === e?.detail) - stepDetail = mod ?? e.detail + if (e?.detail === 'failure') { + stepDetail = flow?.value?.failure_module + } else if (e?.detail === 'preprocessor') { + stepDetail = flow?.value?.preprocessor_module + } else { + stepDetail = dfs(flow?.value?.modules ?? [], (m) => m).find((m) => m?.id === e?.detail) + } + stepDetail = stepDetail ?? e?.detail dispatch('select', stepDetail) }} /> diff --git a/frontend/src/lib/components/FlowGraphViewerStep.svelte b/frontend/src/lib/components/FlowGraphViewerStep.svelte index 789c0eed93d84..b2b7b9d381d00 100644 --- a/frontend/src/lib/components/FlowGraphViewerStep.svelte +++ b/frontend/src/lib/components/FlowGraphViewerStep.svelte @@ -103,12 +103,17 @@ {:else if typeof stepDetail != 'string' && stepDetail.value}
- {#if stepDetail.id} + {#if stepDetail.id && stepDetail.id != 'failure' && stepDetail.id != 'preprocessor'} {stepDetail.id} {/if} - + {#if stepDetail.summary} {stepDetail.summary} {:else if stepDetail.value.type == 'identity'} @@ -124,6 +129,10 @@ Inner flow {:else if stepDetail.value.type == 'whileloopflow'} While loop + {:else if stepDetail.id === 'failure'} + Error handler + {:else if stepDetail.id === 'preprocessor'} + Preprocessor {:else} Anonymous step {/if} @@ -147,10 +156,12 @@ An identity step returns its inputs as outputs

{:else if stepDetail.value.type == 'rawscript'} -
-

Step Inputs

- -
+ {#if stepDetail.id !== 'preprocessor'} +
+

Step Inputs

+ +
+ {/if}
@@ -180,10 +191,12 @@
{:else if stepDetail.value.type == 'script'} -
-

Step Inputs

- -
+ {#if stepDetail.id !== 'preprocessor'} +
+

Step Inputs

+ +
+ {/if} {#if stepDetail.value.path.startsWith('hub/')}
diff --git a/frontend/src/lib/components/graph/graphBuilder.ts b/frontend/src/lib/components/graph/graphBuilder.ts index 6805627db0229..92f6b4942336f 100644 --- a/frontend/src/lib/components/graph/graphBuilder.ts +++ b/frontend/src/lib/components/graph/graphBuilder.ts @@ -451,6 +451,10 @@ export default function graphBuilder( addEdge(id, 'Input', { type: 'empty' }) } + if (failureModule && !extra.flowModuleStates) { + addNode(failureModule, 0, 'module') + } + Object.keys(parents).forEach((key) => { const node = nodes.find((n) => n.id === key)