@pgflow/core 0.0.0-array-map-steps-302d00a8-20250922101336 → 0.0.0-test-snapshot-releases-8d5d9bc1-20250922101013
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -7
- package/package.json +2 -2
- package/dist/ATLAS.md +0 -32
- package/dist/CHANGELOG.md +0 -645
- package/dist/PLAN_race_condition_testing.md +0 -176
- package/dist/PgflowSqlClient.d.ts +0 -17
- package/dist/PgflowSqlClient.d.ts.map +0 -1
- package/dist/PgflowSqlClient.js +0 -70
- package/dist/README.md +0 -399
- package/dist/database-types.d.ts +0 -832
- package/dist/database-types.d.ts.map +0 -1
- package/dist/database-types.js +0 -8
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/package.json +0 -32
- package/dist/supabase/migrations/20250429164909_pgflow_initial.sql +0 -579
- package/dist/supabase/migrations/20250517072017_pgflow_fix_poll_for_tasks_to_use_separate_statement_for_polling.sql +0 -101
- package/dist/supabase/migrations/20250609105135_pgflow_add_start_tasks_and_started_status.sql +0 -371
- package/dist/supabase/migrations/20250610180554_pgflow_add_set_vt_batch_and_use_it_in_start_tasks.sql +0 -127
- package/dist/supabase/migrations/20250614124241_pgflow_add_realtime.sql +0 -501
- package/dist/supabase/migrations/20250619195327_pgflow_fix_fail_task_missing_realtime_event.sql +0 -185
- package/dist/supabase/migrations/20250627090700_pgflow_fix_function_search_paths.sql +0 -6
- package/dist/supabase/migrations/20250707210212_pgflow_add_opt_start_delay.sql +0 -103
- package/dist/supabase/migrations/20250719205006_pgflow_worker_deprecation.sql +0 -2
- package/dist/supabase/migrations/20250912075001_pgflow_temp_pr1_schema.sql +0 -185
- package/dist/supabase/migrations/20250912080800_pgflow_temp_pr2_root_maps.sql +0 -95
- package/dist/supabase/migrations/20250912125339_pgflow_TEMP_task_spawning_optimization.sql +0 -146
- package/dist/supabase/migrations/20250916093518_pgflow_temp_add_cascade_complete.sql +0 -321
- package/dist/supabase/migrations/20250916142327_pgflow_temp_make_initial_tasks_nullable.sql +0 -624
- package/dist/supabase/migrations/20250916203905_pgflow_temp_handle_arrays_in_start_tasks.sql +0 -157
- package/dist/supabase/migrations/20250918042753_pgflow_temp_handle_map_output_aggregation.sql +0 -489
- package/dist/supabase/migrations/20250919101802_pgflow_temp_orphaned_messages_index.sql +0 -688
- package/dist/supabase/migrations/20250919135211_pgflow_temp_return_task_index_in_start_tasks.sql +0 -178
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
- package/dist/types.d.ts +0 -95
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -1
package/dist/supabase/migrations/20250609105135_pgflow_add_start_tasks_and_started_status.sql
DELETED
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
-- Create index "idx_workers_heartbeat" to table: "workers"
|
|
2
|
-
create index "idx_workers_heartbeat" on "pgflow"."workers" ("last_heartbeat_at");
|
|
3
|
-
-- Modify "step_tasks" table
|
|
4
|
-
alter table "pgflow"."step_tasks" drop constraint "valid_status",
|
|
5
|
-
add constraint "valid_status" check (
|
|
6
|
-
status = ANY(array['queued'::text, 'started'::text, 'completed'::text, 'failed'::text])
|
|
7
|
-
),
|
|
8
|
-
add constraint "completed_at_is_after_started_at" check (
|
|
9
|
-
(completed_at is null) or (started_at is null) or (completed_at >= started_at)
|
|
10
|
-
),
|
|
11
|
-
add constraint "failed_at_is_after_started_at" check (
|
|
12
|
-
(failed_at is null) or (started_at is null) or (failed_at >= started_at)
|
|
13
|
-
),
|
|
14
|
-
add constraint "started_at_is_after_queued_at" check ((started_at is null) or (started_at >= queued_at)),
|
|
15
|
-
add column "started_at" timestamptz null,
|
|
16
|
-
add column "last_worker_id" uuid null,
|
|
17
|
-
add constraint "step_tasks_last_worker_id_fkey" foreign key ("last_worker_id") references "pgflow"."workers" (
|
|
18
|
-
"worker_id"
|
|
19
|
-
) on update no action on delete set null;
|
|
20
|
-
-- Create index "idx_step_tasks_last_worker" to table: "step_tasks"
|
|
21
|
-
create index "idx_step_tasks_last_worker" on "pgflow"."step_tasks" ("last_worker_id") where (status = 'started'::text);
|
|
22
|
-
-- Create index "idx_step_tasks_queued_msg" to table: "step_tasks"
|
|
23
|
-
create index "idx_step_tasks_queued_msg" on "pgflow"."step_tasks" ("message_id") where (status = 'queued'::text);
|
|
24
|
-
-- Create index "idx_step_tasks_started" to table: "step_tasks"
|
|
25
|
-
create index "idx_step_tasks_started" on "pgflow"."step_tasks" ("started_at") where (status = 'started'::text);
|
|
26
|
-
-- Modify "complete_task" function
|
|
27
|
-
create or replace function "pgflow"."complete_task"(
|
|
28
|
-
"run_id" uuid, "step_slug" text, "task_index" integer, "output" jsonb
|
|
29
|
-
) returns setof "pgflow"."step_tasks" language plpgsql set "search_path"
|
|
30
|
-
= '' as $$
|
|
31
|
-
begin
|
|
32
|
-
|
|
33
|
-
WITH run_lock AS (
|
|
34
|
-
SELECT * FROM pgflow.runs
|
|
35
|
-
WHERE pgflow.runs.run_id = complete_task.run_id
|
|
36
|
-
FOR UPDATE
|
|
37
|
-
),
|
|
38
|
-
step_lock AS (
|
|
39
|
-
SELECT * FROM pgflow.step_states
|
|
40
|
-
WHERE pgflow.step_states.run_id = complete_task.run_id
|
|
41
|
-
AND pgflow.step_states.step_slug = complete_task.step_slug
|
|
42
|
-
FOR UPDATE
|
|
43
|
-
),
|
|
44
|
-
task AS (
|
|
45
|
-
UPDATE pgflow.step_tasks
|
|
46
|
-
SET
|
|
47
|
-
status = 'completed',
|
|
48
|
-
completed_at = now(),
|
|
49
|
-
output = complete_task.output
|
|
50
|
-
WHERE pgflow.step_tasks.run_id = complete_task.run_id
|
|
51
|
-
AND pgflow.step_tasks.step_slug = complete_task.step_slug
|
|
52
|
-
AND pgflow.step_tasks.task_index = complete_task.task_index
|
|
53
|
-
AND pgflow.step_tasks.status = 'started'
|
|
54
|
-
RETURNING *
|
|
55
|
-
),
|
|
56
|
-
step_state AS (
|
|
57
|
-
UPDATE pgflow.step_states
|
|
58
|
-
SET
|
|
59
|
-
status = CASE
|
|
60
|
-
WHEN pgflow.step_states.remaining_tasks = 1 THEN 'completed' -- Will be 0 after decrement
|
|
61
|
-
ELSE 'started'
|
|
62
|
-
END,
|
|
63
|
-
completed_at = CASE
|
|
64
|
-
WHEN pgflow.step_states.remaining_tasks = 1 THEN now() -- Will be 0 after decrement
|
|
65
|
-
ELSE NULL
|
|
66
|
-
END,
|
|
67
|
-
remaining_tasks = pgflow.step_states.remaining_tasks - 1
|
|
68
|
-
FROM task
|
|
69
|
-
WHERE pgflow.step_states.run_id = complete_task.run_id
|
|
70
|
-
AND pgflow.step_states.step_slug = complete_task.step_slug
|
|
71
|
-
RETURNING pgflow.step_states.*
|
|
72
|
-
),
|
|
73
|
-
-- Find all dependent steps if the current step was completed
|
|
74
|
-
dependent_steps AS (
|
|
75
|
-
SELECT d.step_slug AS dependent_step_slug
|
|
76
|
-
FROM pgflow.deps d
|
|
77
|
-
JOIN step_state s ON s.status = 'completed' AND d.flow_slug = s.flow_slug
|
|
78
|
-
WHERE d.dep_slug = complete_task.step_slug
|
|
79
|
-
ORDER BY d.step_slug -- Ensure consistent ordering
|
|
80
|
-
),
|
|
81
|
-
-- Lock dependent steps before updating
|
|
82
|
-
dependent_steps_lock AS (
|
|
83
|
-
SELECT * FROM pgflow.step_states
|
|
84
|
-
WHERE pgflow.step_states.run_id = complete_task.run_id
|
|
85
|
-
AND pgflow.step_states.step_slug IN (SELECT dependent_step_slug FROM dependent_steps)
|
|
86
|
-
FOR UPDATE
|
|
87
|
-
),
|
|
88
|
-
-- Update all dependent steps
|
|
89
|
-
dependent_steps_update AS (
|
|
90
|
-
UPDATE pgflow.step_states
|
|
91
|
-
SET remaining_deps = pgflow.step_states.remaining_deps - 1
|
|
92
|
-
FROM dependent_steps
|
|
93
|
-
WHERE pgflow.step_states.run_id = complete_task.run_id
|
|
94
|
-
AND pgflow.step_states.step_slug = dependent_steps.dependent_step_slug
|
|
95
|
-
)
|
|
96
|
-
-- Only decrement remaining_steps, don't update status
|
|
97
|
-
UPDATE pgflow.runs
|
|
98
|
-
SET remaining_steps = pgflow.runs.remaining_steps - 1
|
|
99
|
-
FROM step_state
|
|
100
|
-
WHERE pgflow.runs.run_id = complete_task.run_id
|
|
101
|
-
AND step_state.status = 'completed';
|
|
102
|
-
|
|
103
|
-
-- For completed tasks: archive the message
|
|
104
|
-
PERFORM (
|
|
105
|
-
WITH completed_tasks AS (
|
|
106
|
-
SELECT r.flow_slug, st.message_id
|
|
107
|
-
FROM pgflow.step_tasks st
|
|
108
|
-
JOIN pgflow.runs r ON st.run_id = r.run_id
|
|
109
|
-
WHERE st.run_id = complete_task.run_id
|
|
110
|
-
AND st.step_slug = complete_task.step_slug
|
|
111
|
-
AND st.task_index = complete_task.task_index
|
|
112
|
-
AND st.status = 'completed'
|
|
113
|
-
)
|
|
114
|
-
SELECT pgmq.archive(ct.flow_slug, ct.message_id)
|
|
115
|
-
FROM completed_tasks ct
|
|
116
|
-
WHERE EXISTS (SELECT 1 FROM completed_tasks)
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
PERFORM pgflow.start_ready_steps(complete_task.run_id);
|
|
120
|
-
|
|
121
|
-
PERFORM pgflow.maybe_complete_run(complete_task.run_id);
|
|
122
|
-
|
|
123
|
-
RETURN QUERY SELECT *
|
|
124
|
-
FROM pgflow.step_tasks AS step_task
|
|
125
|
-
WHERE step_task.run_id = complete_task.run_id
|
|
126
|
-
AND step_task.step_slug = complete_task.step_slug
|
|
127
|
-
AND step_task.task_index = complete_task.task_index;
|
|
128
|
-
|
|
129
|
-
end;
|
|
130
|
-
$$;
|
|
131
|
-
-- Modify "fail_task" function
|
|
132
|
-
create or replace function "pgflow"."fail_task"(
|
|
133
|
-
"run_id" uuid, "step_slug" text, "task_index" integer, "error_message" text
|
|
134
|
-
) returns setof "pgflow"."step_tasks" language plpgsql set "search_path"
|
|
135
|
-
= '' as $$
|
|
136
|
-
begin
|
|
137
|
-
|
|
138
|
-
WITH run_lock AS (
|
|
139
|
-
SELECT * FROM pgflow.runs
|
|
140
|
-
WHERE pgflow.runs.run_id = fail_task.run_id
|
|
141
|
-
FOR UPDATE
|
|
142
|
-
),
|
|
143
|
-
step_lock AS (
|
|
144
|
-
SELECT * FROM pgflow.step_states
|
|
145
|
-
WHERE pgflow.step_states.run_id = fail_task.run_id
|
|
146
|
-
AND pgflow.step_states.step_slug = fail_task.step_slug
|
|
147
|
-
FOR UPDATE
|
|
148
|
-
),
|
|
149
|
-
flow_info AS (
|
|
150
|
-
SELECT r.flow_slug
|
|
151
|
-
FROM pgflow.runs r
|
|
152
|
-
WHERE r.run_id = fail_task.run_id
|
|
153
|
-
),
|
|
154
|
-
config AS (
|
|
155
|
-
SELECT
|
|
156
|
-
COALESCE(s.opt_max_attempts, f.opt_max_attempts) AS opt_max_attempts,
|
|
157
|
-
COALESCE(s.opt_base_delay, f.opt_base_delay) AS opt_base_delay
|
|
158
|
-
FROM pgflow.steps s
|
|
159
|
-
JOIN pgflow.flows f ON f.flow_slug = s.flow_slug
|
|
160
|
-
JOIN flow_info fi ON fi.flow_slug = s.flow_slug
|
|
161
|
-
WHERE s.flow_slug = fi.flow_slug AND s.step_slug = fail_task.step_slug
|
|
162
|
-
),
|
|
163
|
-
|
|
164
|
-
fail_or_retry_task as (
|
|
165
|
-
UPDATE pgflow.step_tasks as task
|
|
166
|
-
SET
|
|
167
|
-
status = CASE
|
|
168
|
-
WHEN task.attempts_count < (SELECT opt_max_attempts FROM config) THEN 'queued'
|
|
169
|
-
ELSE 'failed'
|
|
170
|
-
END,
|
|
171
|
-
failed_at = CASE
|
|
172
|
-
WHEN task.attempts_count >= (SELECT opt_max_attempts FROM config) THEN now()
|
|
173
|
-
ELSE NULL
|
|
174
|
-
END,
|
|
175
|
-
started_at = CASE
|
|
176
|
-
WHEN task.attempts_count < (SELECT opt_max_attempts FROM config) THEN NULL
|
|
177
|
-
ELSE task.started_at
|
|
178
|
-
END,
|
|
179
|
-
error_message = fail_task.error_message
|
|
180
|
-
WHERE task.run_id = fail_task.run_id
|
|
181
|
-
AND task.step_slug = fail_task.step_slug
|
|
182
|
-
AND task.task_index = fail_task.task_index
|
|
183
|
-
AND task.status = 'started'
|
|
184
|
-
RETURNING *
|
|
185
|
-
),
|
|
186
|
-
maybe_fail_step AS (
|
|
187
|
-
UPDATE pgflow.step_states
|
|
188
|
-
SET
|
|
189
|
-
status = CASE
|
|
190
|
-
WHEN (select fail_or_retry_task.status from fail_or_retry_task) = 'failed' THEN 'failed'
|
|
191
|
-
ELSE pgflow.step_states.status
|
|
192
|
-
END,
|
|
193
|
-
failed_at = CASE
|
|
194
|
-
WHEN (select fail_or_retry_task.status from fail_or_retry_task) = 'failed' THEN now()
|
|
195
|
-
ELSE NULL
|
|
196
|
-
END
|
|
197
|
-
FROM fail_or_retry_task
|
|
198
|
-
WHERE pgflow.step_states.run_id = fail_task.run_id
|
|
199
|
-
AND pgflow.step_states.step_slug = fail_task.step_slug
|
|
200
|
-
RETURNING pgflow.step_states.*
|
|
201
|
-
)
|
|
202
|
-
UPDATE pgflow.runs
|
|
203
|
-
SET status = CASE
|
|
204
|
-
WHEN (select status from maybe_fail_step) = 'failed' THEN 'failed'
|
|
205
|
-
ELSE status
|
|
206
|
-
END,
|
|
207
|
-
failed_at = CASE
|
|
208
|
-
WHEN (select status from maybe_fail_step) = 'failed' THEN now()
|
|
209
|
-
ELSE NULL
|
|
210
|
-
END
|
|
211
|
-
WHERE pgflow.runs.run_id = fail_task.run_id;
|
|
212
|
-
|
|
213
|
-
-- For queued tasks: delay the message for retry with exponential backoff
|
|
214
|
-
PERFORM (
|
|
215
|
-
WITH retry_config AS (
|
|
216
|
-
SELECT
|
|
217
|
-
COALESCE(s.opt_base_delay, f.opt_base_delay) AS base_delay
|
|
218
|
-
FROM pgflow.steps s
|
|
219
|
-
JOIN pgflow.flows f ON f.flow_slug = s.flow_slug
|
|
220
|
-
JOIN pgflow.runs r ON r.flow_slug = f.flow_slug
|
|
221
|
-
WHERE r.run_id = fail_task.run_id
|
|
222
|
-
AND s.step_slug = fail_task.step_slug
|
|
223
|
-
),
|
|
224
|
-
queued_tasks AS (
|
|
225
|
-
SELECT
|
|
226
|
-
r.flow_slug,
|
|
227
|
-
st.message_id,
|
|
228
|
-
pgflow.calculate_retry_delay((SELECT base_delay FROM retry_config), st.attempts_count) AS calculated_delay
|
|
229
|
-
FROM pgflow.step_tasks st
|
|
230
|
-
JOIN pgflow.runs r ON st.run_id = r.run_id
|
|
231
|
-
WHERE st.run_id = fail_task.run_id
|
|
232
|
-
AND st.step_slug = fail_task.step_slug
|
|
233
|
-
AND st.task_index = fail_task.task_index
|
|
234
|
-
AND st.status = 'queued'
|
|
235
|
-
)
|
|
236
|
-
SELECT pgmq.set_vt(qt.flow_slug, qt.message_id, qt.calculated_delay)
|
|
237
|
-
FROM queued_tasks qt
|
|
238
|
-
WHERE EXISTS (SELECT 1 FROM queued_tasks)
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
-- For failed tasks: archive the message
|
|
242
|
-
PERFORM (
|
|
243
|
-
WITH failed_tasks AS (
|
|
244
|
-
SELECT r.flow_slug, st.message_id
|
|
245
|
-
FROM pgflow.step_tasks st
|
|
246
|
-
JOIN pgflow.runs r ON st.run_id = r.run_id
|
|
247
|
-
WHERE st.run_id = fail_task.run_id
|
|
248
|
-
AND st.step_slug = fail_task.step_slug
|
|
249
|
-
AND st.task_index = fail_task.task_index
|
|
250
|
-
AND st.status = 'failed'
|
|
251
|
-
)
|
|
252
|
-
SELECT pgmq.archive(ft.flow_slug, ft.message_id)
|
|
253
|
-
FROM failed_tasks ft
|
|
254
|
-
WHERE EXISTS (SELECT 1 FROM failed_tasks)
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
return query select *
|
|
258
|
-
from pgflow.step_tasks st
|
|
259
|
-
where st.run_id = fail_task.run_id
|
|
260
|
-
and st.step_slug = fail_task.step_slug
|
|
261
|
-
and st.task_index = fail_task.task_index;
|
|
262
|
-
|
|
263
|
-
end;
|
|
264
|
-
$$;
|
|
265
|
-
-- Modify "poll_for_tasks" function
|
|
266
|
-
create or replace function "pgflow"."poll_for_tasks"(
|
|
267
|
-
"queue_name" text,
|
|
268
|
-
"vt" integer,
|
|
269
|
-
"qty" integer,
|
|
270
|
-
"max_poll_seconds" integer default 5,
|
|
271
|
-
"poll_interval_ms" integer default 100
|
|
272
|
-
) returns setof "pgflow"."step_task_record" language plpgsql set "search_path"
|
|
273
|
-
= '' as $$
|
|
274
|
-
begin
|
|
275
|
-
-- DEPRECATED: This function is deprecated and will be removed in a future version.
|
|
276
|
-
-- Please update pgflow to use the new two-phase polling approach.
|
|
277
|
-
-- Run 'npx pgflow install' to update your installation.
|
|
278
|
-
raise notice 'DEPRECATED: poll_for_tasks is deprecated and will be removed. Please update pgflow via "npx pgflow install".';
|
|
279
|
-
|
|
280
|
-
-- Return empty set - no tasks will be processed
|
|
281
|
-
return;
|
|
282
|
-
end;
|
|
283
|
-
$$;
|
|
284
|
-
-- Create "start_tasks" function
|
|
285
|
-
create function "pgflow"."start_tasks"(
|
|
286
|
-
"flow_slug" text, "msg_ids" bigint [], "worker_id" uuid
|
|
287
|
-
) returns setof "pgflow"."step_task_record" language sql set "search_path"
|
|
288
|
-
= '' as $$
|
|
289
|
-
with tasks as (
|
|
290
|
-
select
|
|
291
|
-
task.flow_slug,
|
|
292
|
-
task.run_id,
|
|
293
|
-
task.step_slug,
|
|
294
|
-
task.task_index,
|
|
295
|
-
task.message_id
|
|
296
|
-
from pgflow.step_tasks as task
|
|
297
|
-
where task.flow_slug = start_tasks.flow_slug
|
|
298
|
-
and task.message_id = any(msg_ids)
|
|
299
|
-
and task.status = 'queued'
|
|
300
|
-
),
|
|
301
|
-
start_tasks_update as (
|
|
302
|
-
update pgflow.step_tasks
|
|
303
|
-
set
|
|
304
|
-
attempts_count = attempts_count + 1,
|
|
305
|
-
status = 'started',
|
|
306
|
-
started_at = now(),
|
|
307
|
-
last_worker_id = worker_id
|
|
308
|
-
from tasks
|
|
309
|
-
where step_tasks.message_id = tasks.message_id
|
|
310
|
-
and step_tasks.flow_slug = tasks.flow_slug
|
|
311
|
-
and step_tasks.status = 'queued'
|
|
312
|
-
),
|
|
313
|
-
runs as (
|
|
314
|
-
select
|
|
315
|
-
r.run_id,
|
|
316
|
-
r.input
|
|
317
|
-
from pgflow.runs r
|
|
318
|
-
where r.run_id in (select run_id from tasks)
|
|
319
|
-
),
|
|
320
|
-
deps as (
|
|
321
|
-
select
|
|
322
|
-
st.run_id,
|
|
323
|
-
st.step_slug,
|
|
324
|
-
dep.dep_slug,
|
|
325
|
-
dep_task.output as dep_output
|
|
326
|
-
from tasks st
|
|
327
|
-
join pgflow.deps dep on dep.flow_slug = st.flow_slug and dep.step_slug = st.step_slug
|
|
328
|
-
join pgflow.step_tasks dep_task on
|
|
329
|
-
dep_task.run_id = st.run_id and
|
|
330
|
-
dep_task.step_slug = dep.dep_slug and
|
|
331
|
-
dep_task.status = 'completed'
|
|
332
|
-
),
|
|
333
|
-
deps_outputs as (
|
|
334
|
-
select
|
|
335
|
-
d.run_id,
|
|
336
|
-
d.step_slug,
|
|
337
|
-
jsonb_object_agg(d.dep_slug, d.dep_output) as deps_output
|
|
338
|
-
from deps d
|
|
339
|
-
group by d.run_id, d.step_slug
|
|
340
|
-
),
|
|
341
|
-
timeouts as (
|
|
342
|
-
select
|
|
343
|
-
task.message_id,
|
|
344
|
-
task.flow_slug,
|
|
345
|
-
coalesce(step.opt_timeout, flow.opt_timeout) + 2 as vt_delay
|
|
346
|
-
from tasks task
|
|
347
|
-
join pgflow.flows flow on flow.flow_slug = task.flow_slug
|
|
348
|
-
join pgflow.steps step on step.flow_slug = task.flow_slug and step.step_slug = task.step_slug
|
|
349
|
-
)
|
|
350
|
-
select
|
|
351
|
-
st.flow_slug,
|
|
352
|
-
st.run_id,
|
|
353
|
-
st.step_slug,
|
|
354
|
-
jsonb_build_object('run', r.input) ||
|
|
355
|
-
coalesce(dep_out.deps_output, '{}'::jsonb) as input,
|
|
356
|
-
st.message_id as msg_id
|
|
357
|
-
from tasks st
|
|
358
|
-
join runs r on st.run_id = r.run_id
|
|
359
|
-
left join deps_outputs dep_out on
|
|
360
|
-
dep_out.run_id = st.run_id and
|
|
361
|
-
dep_out.step_slug = st.step_slug
|
|
362
|
-
cross join lateral (
|
|
363
|
-
-- TODO: this is slow because it calls set_vt for each row, and set_vt
|
|
364
|
-
-- builds dynamic query from string every time it is called
|
|
365
|
-
-- implement set_vt_batch(msgs_ids bigint[], vt_delays int[])
|
|
366
|
-
select pgmq.set_vt(t.flow_slug, st.message_id, t.vt_delay)
|
|
367
|
-
from timeouts t
|
|
368
|
-
where t.message_id = st.message_id
|
|
369
|
-
and t.flow_slug = st.flow_slug
|
|
370
|
-
) set_vt
|
|
371
|
-
$$;
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
-- Create "set_vt_batch" function
|
|
2
|
-
CREATE FUNCTION "pgflow"."set_vt_batch" ("queue_name" text, "msg_ids" bigint[], "vt_offsets" integer[]) RETURNS SETOF pgmq.message_record LANGUAGE plpgsql AS $$
|
|
3
|
-
DECLARE
|
|
4
|
-
qtable TEXT := pgmq.format_table_name(queue_name, 'q');
|
|
5
|
-
sql TEXT;
|
|
6
|
-
BEGIN
|
|
7
|
-
/* ---------- safety checks ---------------------------------------------------- */
|
|
8
|
-
IF msg_ids IS NULL OR vt_offsets IS NULL OR array_length(msg_ids, 1) = 0 THEN
|
|
9
|
-
RETURN; -- nothing to do, return empty set
|
|
10
|
-
END IF;
|
|
11
|
-
|
|
12
|
-
IF array_length(msg_ids, 1) IS DISTINCT FROM array_length(vt_offsets, 1) THEN
|
|
13
|
-
RAISE EXCEPTION
|
|
14
|
-
'msg_ids length (%) must equal vt_offsets length (%)',
|
|
15
|
-
array_length(msg_ids, 1), array_length(vt_offsets, 1);
|
|
16
|
-
END IF;
|
|
17
|
-
|
|
18
|
-
/* ---------- dynamic statement ------------------------------------------------ */
|
|
19
|
-
/* One UPDATE joins with the unnested arrays */
|
|
20
|
-
sql := format(
|
|
21
|
-
$FMT$
|
|
22
|
-
WITH input (msg_id, vt_offset) AS (
|
|
23
|
-
SELECT unnest($1)::bigint
|
|
24
|
-
, unnest($2)::int
|
|
25
|
-
)
|
|
26
|
-
UPDATE pgmq.%I q
|
|
27
|
-
SET vt = clock_timestamp() + make_interval(secs => input.vt_offset),
|
|
28
|
-
read_ct = read_ct -- no change, but keeps RETURNING list aligned
|
|
29
|
-
FROM input
|
|
30
|
-
WHERE q.msg_id = input.msg_id
|
|
31
|
-
RETURNING q.msg_id,
|
|
32
|
-
q.read_ct,
|
|
33
|
-
q.enqueued_at,
|
|
34
|
-
q.vt,
|
|
35
|
-
q.message
|
|
36
|
-
$FMT$,
|
|
37
|
-
qtable
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
RETURN QUERY EXECUTE sql USING msg_ids, vt_offsets;
|
|
41
|
-
END;
|
|
42
|
-
$$;
|
|
43
|
-
-- Modify "start_tasks" function
|
|
44
|
-
CREATE OR REPLACE FUNCTION "pgflow"."start_tasks" ("flow_slug" text, "msg_ids" bigint[], "worker_id" uuid) RETURNS SETOF "pgflow"."step_task_record" LANGUAGE sql SET "search_path" = '' AS $$
|
|
45
|
-
with tasks as (
|
|
46
|
-
select
|
|
47
|
-
task.flow_slug,
|
|
48
|
-
task.run_id,
|
|
49
|
-
task.step_slug,
|
|
50
|
-
task.task_index,
|
|
51
|
-
task.message_id
|
|
52
|
-
from pgflow.step_tasks as task
|
|
53
|
-
where task.flow_slug = start_tasks.flow_slug
|
|
54
|
-
and task.message_id = any(msg_ids)
|
|
55
|
-
and task.status = 'queued'
|
|
56
|
-
),
|
|
57
|
-
start_tasks_update as (
|
|
58
|
-
update pgflow.step_tasks
|
|
59
|
-
set
|
|
60
|
-
attempts_count = attempts_count + 1,
|
|
61
|
-
status = 'started',
|
|
62
|
-
started_at = now(),
|
|
63
|
-
last_worker_id = worker_id
|
|
64
|
-
from tasks
|
|
65
|
-
where step_tasks.message_id = tasks.message_id
|
|
66
|
-
and step_tasks.flow_slug = tasks.flow_slug
|
|
67
|
-
and step_tasks.status = 'queued'
|
|
68
|
-
),
|
|
69
|
-
runs as (
|
|
70
|
-
select
|
|
71
|
-
r.run_id,
|
|
72
|
-
r.input
|
|
73
|
-
from pgflow.runs r
|
|
74
|
-
where r.run_id in (select run_id from tasks)
|
|
75
|
-
),
|
|
76
|
-
deps as (
|
|
77
|
-
select
|
|
78
|
-
st.run_id,
|
|
79
|
-
st.step_slug,
|
|
80
|
-
dep.dep_slug,
|
|
81
|
-
dep_task.output as dep_output
|
|
82
|
-
from tasks st
|
|
83
|
-
join pgflow.deps dep on dep.flow_slug = st.flow_slug and dep.step_slug = st.step_slug
|
|
84
|
-
join pgflow.step_tasks dep_task on
|
|
85
|
-
dep_task.run_id = st.run_id and
|
|
86
|
-
dep_task.step_slug = dep.dep_slug and
|
|
87
|
-
dep_task.status = 'completed'
|
|
88
|
-
),
|
|
89
|
-
deps_outputs as (
|
|
90
|
-
select
|
|
91
|
-
d.run_id,
|
|
92
|
-
d.step_slug,
|
|
93
|
-
jsonb_object_agg(d.dep_slug, d.dep_output) as deps_output
|
|
94
|
-
from deps d
|
|
95
|
-
group by d.run_id, d.step_slug
|
|
96
|
-
),
|
|
97
|
-
timeouts as (
|
|
98
|
-
select
|
|
99
|
-
task.message_id,
|
|
100
|
-
task.flow_slug,
|
|
101
|
-
coalesce(step.opt_timeout, flow.opt_timeout) + 2 as vt_delay
|
|
102
|
-
from tasks task
|
|
103
|
-
join pgflow.flows flow on flow.flow_slug = task.flow_slug
|
|
104
|
-
join pgflow.steps step on step.flow_slug = task.flow_slug and step.step_slug = task.step_slug
|
|
105
|
-
),
|
|
106
|
-
-- Batch update visibility timeouts for all messages
|
|
107
|
-
set_vt_batch as (
|
|
108
|
-
select pgflow.set_vt_batch(
|
|
109
|
-
start_tasks.flow_slug,
|
|
110
|
-
array_agg(t.message_id order by t.message_id),
|
|
111
|
-
array_agg(t.vt_delay order by t.message_id)
|
|
112
|
-
)
|
|
113
|
-
from timeouts t
|
|
114
|
-
)
|
|
115
|
-
select
|
|
116
|
-
st.flow_slug,
|
|
117
|
-
st.run_id,
|
|
118
|
-
st.step_slug,
|
|
119
|
-
jsonb_build_object('run', r.input) ||
|
|
120
|
-
coalesce(dep_out.deps_output, '{}'::jsonb) as input,
|
|
121
|
-
st.message_id as msg_id
|
|
122
|
-
from tasks st
|
|
123
|
-
join runs r on st.run_id = r.run_id
|
|
124
|
-
left join deps_outputs dep_out on
|
|
125
|
-
dep_out.run_id = st.run_id and
|
|
126
|
-
dep_out.step_slug = st.step_slug
|
|
127
|
-
$$;
|