Skip to content

Commit 960485f

Browse files
committed
Rename when_failed to when_exhausted for better naming consistency
1 parent 192d2c0 commit 960485f

54 files changed

Lines changed: 420 additions & 422 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/conditional-step-execution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Add conditional step execution with skip infrastructure
1919

2020
**Schema Changes:**
2121

22-
- New columns: required_input_pattern, forbidden_input_pattern, when_unmet, when_failed, skip_reason, skipped_at
22+
- New columns: required_input_pattern, forbidden_input_pattern, when_unmet, when_exhausted, skip_reason, skipped_at
2323
- New step status: 'skipped'
2424
- New function: cascade_skip_steps() for skip propagation
2525
- FlowShape condition fields for auto-compilation drift detection

.ignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
!.claude
2+
!.claude/*
23
!.notes

pkgs/core/schemas/0050_tables_definitions.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ create table pgflow.steps (
2727
required_input_pattern jsonb, -- JSON pattern for @> containment check (if)
2828
forbidden_input_pattern jsonb, -- JSON pattern for NOT @> containment check (ifNot)
2929
when_unmet text not null default 'skip', -- What to do when condition not met (skip is natural default)
30-
when_failed text not null default 'fail', -- What to do when handler fails after retries
30+
when_exhausted text not null default 'fail', -- What to do when handler fails after retries
3131
created_at timestamptz not null default now(),
3232
primary key (flow_slug, step_slug),
3333
unique (flow_slug, step_index), -- Ensure step_index is unique within a flow
@@ -38,7 +38,7 @@ create table pgflow.steps (
3838
constraint opt_timeout_is_positive check (opt_timeout is null or opt_timeout > 0),
3939
constraint opt_start_delay_is_nonnegative check (opt_start_delay is null or opt_start_delay >= 0),
4040
constraint when_unmet_is_valid check (when_unmet in ('fail', 'skip', 'skip-cascade')),
41-
constraint when_failed_is_valid check (when_failed in ('fail', 'skip', 'skip-cascade'))
41+
constraint when_exhausted_is_valid check (when_exhausted in ('fail', 'skip', 'skip-cascade'))
4242
);
4343

4444
-- Dependencies table - stores relationships between steps

pkgs/core/schemas/0100_function__cascade_force_skip_steps.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- _cascade_force_skip_steps: Skip a step and cascade to all downstream dependents
2-
-- Used when a condition is unmet (whenUnmet: skip-cascade) or handler fails (whenFailed: skip-cascade)
2+
-- Used when a condition is unmet (whenUnmet: skip-cascade) or handler fails (whenExhausted: skip-cascade)
33
create or replace function pgflow._cascade_force_skip_steps(
44
run_id uuid,
55
step_slug text,

pkgs/core/schemas/0100_function_add_step.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ create or replace function pgflow.add_step(
1010
required_input_pattern jsonb default null,
1111
forbidden_input_pattern jsonb default null,
1212
when_unmet text default 'skip',
13-
when_failed text default 'fail'
13+
when_exhausted text default 'fail'
1414
)
1515
returns pgflow.steps
1616
language plpgsql
@@ -41,7 +41,7 @@ BEGIN
4141
INSERT INTO pgflow.steps (
4242
flow_slug, step_slug, step_type, step_index, deps_count,
4343
opt_max_attempts, opt_base_delay, opt_timeout, opt_start_delay,
44-
required_input_pattern, forbidden_input_pattern, when_unmet, when_failed
44+
required_input_pattern, forbidden_input_pattern, when_unmet, when_exhausted
4545
)
4646
VALUES (
4747
add_step.flow_slug,
@@ -56,7 +56,7 @@ BEGIN
5656
add_step.required_input_pattern,
5757
add_step.forbidden_input_pattern,
5858
add_step.when_unmet,
59-
add_step.when_failed
59+
add_step.when_exhausted
6060
)
6161
ON CONFLICT ON CONSTRAINT steps_pkey
6262
DO UPDATE SET step_slug = EXCLUDED.step_slug

pkgs/core/schemas/0100_function_compare_flow_shapes.sql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,15 @@ BEGIN
121121
);
122122
END IF;
123123

124-
-- Compare whenFailed (structural - affects DAG execution semantics)
125-
IF v_local_step->>'whenFailed' != v_db_step->>'whenFailed' THEN
124+
-- Compare whenExhausted (structural - affects DAG execution semantics)
125+
IF v_local_step->>'whenExhausted' != v_db_step->>'whenExhausted' THEN
126126
v_differences := array_append(
127127
v_differences,
128128
format(
129-
$$Step at index %s: whenFailed differs '%s' vs '%s'$$,
129+
$$Step at index %s: whenExhausted differs '%s' vs '%s'$$,
130130
v_idx,
131-
v_local_step->>'whenFailed',
132-
v_db_step->>'whenFailed'
131+
v_local_step->>'whenExhausted',
132+
v_db_step->>'whenExhausted'
133133
)
134134
);
135135
END IF;

pkgs/core/schemas/0100_function_create_flow_from_shape.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ BEGIN
4949
start_delay => (v_step_options->>'startDelay')::int,
5050
step_type => v_step->>'stepType',
5151
when_unmet => v_step->>'whenUnmet',
52-
when_failed => v_step->>'whenFailed',
52+
when_exhausted => v_step->>'whenExhausted',
5353
required_input_pattern => CASE
5454
WHEN (v_step->'requiredInputPattern'->>'defined')::boolean
5555
THEN v_step->'requiredInputPattern'->'value'

pkgs/core/schemas/0100_function_fail_task.sql

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ DECLARE
1313
v_run_failed boolean;
1414
v_step_failed boolean;
1515
v_step_skipped boolean;
16-
v_when_failed text;
16+
v_when_exhausted text;
1717
v_task_exhausted boolean; -- True if task has exhausted retries
1818
v_flow_slug_for_deps text; -- Used for decrementing remaining_deps on plain skip
1919
begin
@@ -63,11 +63,11 @@ flow_info AS (
6363
FROM pgflow.runs r
6464
WHERE r.run_id = fail_task.run_id
6565
),
66-
config AS (
66+
config AS (
6767
SELECT
6868
COALESCE(s.opt_max_attempts, f.opt_max_attempts) AS opt_max_attempts,
6969
COALESCE(s.opt_base_delay, f.opt_base_delay) AS opt_base_delay,
70-
s.when_failed
70+
s.when_exhausted
7171
FROM pgflow.steps s
7272
JOIN pgflow.flows f ON f.flow_slug = s.flow_slug
7373
JOIN flow_info fi ON fi.flow_slug = s.flow_slug
@@ -95,53 +95,53 @@ fail_or_retry_task as (
9595
AND task.status = 'started'
9696
RETURNING *
9797
),
98-
-- Determine if task exhausted retries and get when_failed mode
99-
task_status AS (
100-
SELECT
101-
(select status from fail_or_retry_task) AS new_task_status,
102-
(select when_failed from config) AS when_failed_mode,
98+
-- Determine if task exhausted retries and get when_exhausted mode
99+
task_status AS (
100+
SELECT
101+
(select status from fail_or_retry_task) AS new_task_status,
102+
(select when_exhausted from config) AS when_exhausted_mode,
103103
-- Task is exhausted when it's failed (no more retries)
104104
((select status from fail_or_retry_task) = 'failed') AS is_exhausted
105105
),
106106
maybe_fail_step AS (
107107
UPDATE pgflow.step_states
108108
SET
109-
-- Status logic:
110-
-- - If task not exhausted (retrying): keep current status
111-
-- - If exhausted AND when_failed='fail': set to 'failed'
112-
-- - If exhausted AND when_failed IN ('skip', 'skip-cascade'): set to 'skipped'
113-
status = CASE
114-
WHEN NOT (select is_exhausted from task_status) THEN pgflow.step_states.status
115-
WHEN (select when_failed_mode from task_status) = 'fail' THEN 'failed'
116-
ELSE 'skipped' -- skip or skip-cascade
117-
END,
109+
-- Status logic:
110+
-- - If task not exhausted (retrying): keep current status
111+
-- - If exhausted AND when_exhausted='fail': set to 'failed'
112+
-- - If exhausted AND when_exhausted IN ('skip', 'skip-cascade'): set to 'skipped'
113+
status = CASE
114+
WHEN NOT (select is_exhausted from task_status) THEN pgflow.step_states.status
115+
WHEN (select when_exhausted_mode from task_status) = 'fail' THEN 'failed'
116+
ELSE 'skipped' -- skip or skip-cascade
117+
END,
118118
failed_at = CASE
119-
WHEN (select is_exhausted from task_status) AND (select when_failed_mode from task_status) = 'fail' THEN now()
120-
ELSE NULL
121-
END,
119+
WHEN (select is_exhausted from task_status) AND (select when_exhausted_mode from task_status) = 'fail' THEN now()
120+
ELSE NULL
121+
END,
122122
error_message = CASE
123123
WHEN (select is_exhausted from task_status) THEN fail_task.error_message
124124
ELSE NULL
125125
END,
126126
skip_reason = CASE
127-
WHEN (select is_exhausted from task_status) AND (select when_failed_mode from task_status) IN ('skip', 'skip-cascade') THEN 'handler_failed'
127+
WHEN (select is_exhausted from task_status) AND (select when_exhausted_mode from task_status) IN ('skip', 'skip-cascade') THEN 'handler_failed'
128128
ELSE pgflow.step_states.skip_reason
129129
END,
130130
skipped_at = CASE
131-
WHEN (select is_exhausted from task_status) AND (select when_failed_mode from task_status) IN ('skip', 'skip-cascade') THEN now()
131+
WHEN (select is_exhausted from task_status) AND (select when_exhausted_mode from task_status) IN ('skip', 'skip-cascade') THEN now()
132132
ELSE pgflow.step_states.skipped_at
133133
END,
134134
-- Clear remaining_tasks when skipping (required by remaining_tasks_state_consistency constraint)
135135
remaining_tasks = CASE
136-
WHEN (select is_exhausted from task_status) AND (select when_failed_mode from task_status) IN ('skip', 'skip-cascade') THEN NULL
136+
WHEN (select is_exhausted from task_status) AND (select when_exhausted_mode from task_status) IN ('skip', 'skip-cascade') THEN NULL
137137
ELSE pgflow.step_states.remaining_tasks
138138
END
139139
FROM fail_or_retry_task
140140
WHERE pgflow.step_states.run_id = fail_task.run_id
141141
AND pgflow.step_states.step_slug = fail_task.step_slug
142142
RETURNING pgflow.step_states.*
143143
)
144-
-- Update run status: only fail when when_failed='fail' and step was failed
144+
-- Update run status: only fail when when_exhausted='fail' and step was failed
145145
UPDATE pgflow.runs
146146
SET status = CASE
147147
WHEN (select status from maybe_fail_step) = 'failed' THEN 'failed'
@@ -159,9 +159,9 @@ SET status = CASE
159159
WHERE pgflow.runs.run_id = fail_task.run_id
160160
RETURNING (status = 'failed') INTO v_run_failed;
161161

162-
-- Capture when_failed mode and check if step was skipped for later processing
163-
SELECT s.when_failed INTO v_when_failed
164-
FROM pgflow.steps s
162+
-- Capture when_exhausted mode and check if step was skipped for later processing
163+
SELECT s.when_exhausted INTO v_when_exhausted
164+
FROM pgflow.steps s
165165
JOIN pgflow.runs r ON r.flow_slug = s.flow_slug
166166
WHERE r.run_id = fail_task.run_id
167167
AND s.step_slug = fail_task.step_slug;
@@ -194,8 +194,8 @@ IF v_step_failed THEN
194194
);
195195
END IF;
196196

197-
-- Handle step skipping (when_failed = 'skip' or 'skip-cascade')
198-
IF v_step_skipped THEN
197+
-- Handle step skipping (when_exhausted = 'skip' or 'skip-cascade')
198+
IF v_step_skipped THEN
199199
-- Send broadcast event for step skipped
200200
PERFORM realtime.send(
201201
jsonb_build_object(
@@ -212,8 +212,8 @@ IF v_step_skipped THEN
212212
false
213213
);
214214

215-
-- For skip-cascade: cascade skip to all downstream dependents
216-
IF v_when_failed = 'skip-cascade' THEN
215+
-- For skip-cascade: cascade skip to all downstream dependents
216+
IF v_when_exhausted = 'skip-cascade' THEN
217217
PERFORM pgflow._cascade_force_skip_steps(fail_task.run_id, fail_task.step_slug, 'handler_failed');
218218
ELSE
219219
-- For plain 'skip': decrement remaining_deps on dependent steps

pkgs/core/schemas/0100_function_get_flow_shape.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ as $$
2424
'[]'::jsonb
2525
),
2626
'whenUnmet', step.when_unmet,
27-
'whenFailed', step.when_failed,
27+
'whenExhausted', step.when_exhausted,
2828
'requiredInputPattern', CASE
2929
WHEN step.required_input_pattern IS NULL
3030
THEN '{"defined": false}'::jsonb

pkgs/core/src/database-types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ export type Database = {
299299
step_index: number
300300
step_slug: string
301301
step_type: string
302-
when_failed: string
302+
when_exhausted: string
303303
when_unmet: string
304304
}
305305
Insert: {
@@ -315,7 +315,7 @@ export type Database = {
315315
step_index?: number
316316
step_slug: string
317317
step_type?: string
318-
when_failed?: string
318+
when_exhausted?: string
319319
when_unmet?: string
320320
}
321321
Update: {
@@ -331,7 +331,7 @@ export type Database = {
331331
step_index?: number
332332
step_slug?: string
333333
step_type?: string
334-
when_failed?: string
334+
when_exhausted?: string
335335
when_unmet?: string
336336
}
337337
Relationships: [
@@ -431,7 +431,7 @@ export type Database = {
431431
step_slug: string
432432
step_type?: string
433433
timeout?: number
434-
when_failed?: string
434+
when_exhausted?: string
435435
when_unmet?: string
436436
}
437437
Returns: {
@@ -447,7 +447,7 @@ export type Database = {
447447
step_index: number
448448
step_slug: string
449449
step_type: string
450-
when_failed: string
450+
when_exhausted: string
451451
when_unmet: string
452452
}
453453
SetofOptions: {

0 commit comments

Comments
 (0)