@pgflow/core 0.0.5 → 0.0.7
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/{CHANGELOG.md → dist/CHANGELOG.md} +6 -0
- package/package.json +8 -5
- package/__tests__/mocks/index.ts +0 -1
- package/__tests__/mocks/postgres.ts +0 -37
- package/__tests__/types/PgflowSqlClient.test-d.ts +0 -59
- package/docs/options_for_flow_and_steps.md +0 -75
- package/docs/pgflow-blob-reference-system.md +0 -179
- package/eslint.config.cjs +0 -22
- package/example-flow.mermaid +0 -5
- package/example-flow.svg +0 -1
- package/flow-lifecycle.mermaid +0 -83
- package/flow-lifecycle.svg +0 -1
- package/out-tsc/vitest/__tests__/mocks/index.d.ts +0 -2
- package/out-tsc/vitest/__tests__/mocks/index.d.ts.map +0 -1
- package/out-tsc/vitest/__tests__/mocks/postgres.d.ts +0 -15
- package/out-tsc/vitest/__tests__/mocks/postgres.d.ts.map +0 -1
- package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts +0 -2
- package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts.map +0 -1
- package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +0 -1
- package/out-tsc/vitest/vite.config.d.ts +0 -3
- package/out-tsc/vitest/vite.config.d.ts.map +0 -1
- package/pkgs/core/dist/index.js +0 -54
- package/pkgs/core/dist/pkgs/core/LICENSE.md +0 -660
- package/pkgs/core/dist/pkgs/core/README.md +0 -373
- package/pkgs/dsl/dist/index.js +0 -123
- package/pkgs/dsl/dist/pkgs/dsl/README.md +0 -11
- package/pkgs/edge-worker/dist/index.js +0 -953
- package/pkgs/edge-worker/dist/index.js.map +0 -7
- package/pkgs/edge-worker/dist/pkgs/edge-worker/LICENSE.md +0 -660
- package/pkgs/edge-worker/dist/pkgs/edge-worker/README.md +0 -46
- package/pkgs/example-flows/dist/index.js +0 -152
- package/pkgs/example-flows/dist/pkgs/example-flows/README.md +0 -11
- package/project.json +0 -125
- package/prompts/architect.md +0 -87
- package/prompts/condition.md +0 -33
- package/prompts/declarative_sql.md +0 -15
- package/prompts/deps_in_payloads.md +0 -20
- package/prompts/dsl-multi-arg.ts +0 -48
- package/prompts/dsl-options.md +0 -39
- package/prompts/dsl-single-arg.ts +0 -51
- package/prompts/dsl-two-arg.ts +0 -61
- package/prompts/dsl.md +0 -119
- package/prompts/fanout_steps.md +0 -1
- package/prompts/json_schemas.md +0 -36
- package/prompts/one_shot.md +0 -286
- package/prompts/pgtap.md +0 -229
- package/prompts/sdk.md +0 -59
- package/prompts/step_types.md +0 -62
- package/prompts/versioning.md +0 -16
- package/queries/fail_permanently.sql +0 -17
- package/queries/fail_task.sql +0 -21
- package/queries/sequential.sql +0 -47
- package/queries/two_roots_left_right.sql +0 -59
- package/schema.svg +0 -1
- package/scripts/colorize-pgtap-output.awk +0 -72
- package/scripts/run-test-with-colors +0 -5
- package/scripts/watch-test +0 -7
- package/src/PgflowSqlClient.ts +0 -85
- package/src/database-types.ts +0 -759
- package/src/index.ts +0 -3
- package/src/types.ts +0 -103
- package/supabase/config.toml +0 -32
- package/supabase/seed.sql +0 -202
- package/supabase/tests/add_step/basic_step_addition.test.sql +0 -29
- package/supabase/tests/add_step/circular_dependency.test.sql +0 -21
- package/supabase/tests/add_step/flow_isolation.test.sql +0 -26
- package/supabase/tests/add_step/idempotent_step_addition.test.sql +0 -20
- package/supabase/tests/add_step/invalid_step_slug.test.sql +0 -16
- package/supabase/tests/add_step/nonexistent_dependency.test.sql +0 -16
- package/supabase/tests/add_step/nonexistent_flow.test.sql +0 -13
- package/supabase/tests/add_step/options.test.sql +0 -66
- package/supabase/tests/add_step/step_with_dependency.test.sql +0 -36
- package/supabase/tests/add_step/step_with_multiple_dependencies.test.sql +0 -46
- package/supabase/tests/complete_task/archives_message.test.sql +0 -67
- package/supabase/tests/complete_task/completes_run_if_no_more_remaining_steps.test.sql +0 -62
- package/supabase/tests/complete_task/completes_task_and_updates_dependents.test.sql +0 -64
- package/supabase/tests/complete_task/decrements_remaining_steps_if_completing_step.test.sql +0 -62
- package/supabase/tests/complete_task/saves_output_when_completing_run.test.sql +0 -57
- package/supabase/tests/create_flow/flow_creation.test.sql +0 -27
- package/supabase/tests/create_flow/idempotency_and_duplicates.test.sql +0 -26
- package/supabase/tests/create_flow/invalid_slug.test.sql +0 -13
- package/supabase/tests/create_flow/options.test.sql +0 -57
- package/supabase/tests/fail_task/exponential_backoff.test.sql +0 -70
- package/supabase/tests/fail_task/mark_as_failed_if_no_retries_available.test.sql +0 -49
- package/supabase/tests/fail_task/respects_flow_retry_settings.test.sql +0 -48
- package/supabase/tests/fail_task/respects_step_retry_settings.test.sql +0 -48
- package/supabase/tests/fail_task/retry_task_if_retries_available.test.sql +0 -39
- package/supabase/tests/is_valid_slug.test.sql +0 -72
- package/supabase/tests/poll_for_tasks/builds_proper_input_from_deps_outputs.test.sql +0 -35
- package/supabase/tests/poll_for_tasks/hides_messages.test.sql +0 -35
- package/supabase/tests/poll_for_tasks/increments_attempts_count.test.sql +0 -35
- package/supabase/tests/poll_for_tasks/multiple_task_processing.test.sql +0 -24
- package/supabase/tests/poll_for_tasks/polls_only_queued_tasks.test.sql +0 -35
- package/supabase/tests/poll_for_tasks/reads_messages.test.sql +0 -38
- package/supabase/tests/poll_for_tasks/returns_no_tasks_if_no_step_task_for_message.test.sql +0 -34
- package/supabase/tests/poll_for_tasks/returns_no_tasks_if_queue_is_empty.test.sql +0 -19
- package/supabase/tests/poll_for_tasks/returns_no_tasks_when_qty_set_to_0.test.sql +0 -22
- package/supabase/tests/poll_for_tasks/sets_vt_delay_based_on_opt_timeout.test.sql +0 -41
- package/supabase/tests/poll_for_tasks/tasks_reapppear_if_not_processed_in_time.test.sql +0 -59
- package/supabase/tests/start_flow/creates_run.test.sql +0 -24
- package/supabase/tests/start_flow/creates_step_states_for_all_steps.test.sql +0 -25
- package/supabase/tests/start_flow/creates_step_tasks_only_for_root_steps.test.sql +0 -54
- package/supabase/tests/start_flow/returns_run.test.sql +0 -24
- package/supabase/tests/start_flow/sends_messages_on_the_queue.test.sql +0 -50
- package/supabase/tests/start_flow/starts_only_root_steps.test.sql +0 -21
- package/supabase/tests/step_dsl_is_idempotent.test.sql +0 -34
- package/tsconfig.json +0 -16
- package/tsconfig.lib.json +0 -26
- package/tsconfig.spec.json +0 -35
- package/vite.config.ts +0 -57
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(5);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP
|
|
7
|
-
select pgflow.start_flow('sequential', '{"test": true}'::JSONB);
|
|
8
|
-
|
|
9
|
-
-- TEST: First message shoud be in the queue
|
|
10
|
-
select is(
|
|
11
|
-
(select message ->> 'step_slug' from pgmq.q_sequential limit 1),
|
|
12
|
-
'first',
|
|
13
|
-
'First message should be in the queue'
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- SETUP
|
|
17
|
-
select pgflow.complete_task(
|
|
18
|
-
(select run_id from pgflow.runs limit 1),
|
|
19
|
-
'first',
|
|
20
|
-
0,
|
|
21
|
-
'"first was successful"'::JSONB
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
-- TEST: First message shoud be archived
|
|
25
|
-
select is(
|
|
26
|
-
(
|
|
27
|
-
select count(*)::INT
|
|
28
|
-
from pgmq.q_sequential
|
|
29
|
-
where message ->> 'step_slug' = 'first'
|
|
30
|
-
),
|
|
31
|
-
0::INT,
|
|
32
|
-
'There should be no messages in the queue'
|
|
33
|
-
);
|
|
34
|
-
select is(
|
|
35
|
-
(
|
|
36
|
-
select count(*)::INT
|
|
37
|
-
from pgmq.a_sequential
|
|
38
|
-
where message ->> 'step_slug' = 'first'
|
|
39
|
-
limit 1
|
|
40
|
-
),
|
|
41
|
-
1::INT,
|
|
42
|
-
'The message should be archived'
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
-- TEST: Other messages shoud not be archived
|
|
46
|
-
select is(
|
|
47
|
-
(
|
|
48
|
-
select count(*)::INT
|
|
49
|
-
from pgmq.q_sequential
|
|
50
|
-
where message ->> 'step_slug' = 'second'
|
|
51
|
-
),
|
|
52
|
-
1::INT,
|
|
53
|
-
'There should be no messages in the queue'
|
|
54
|
-
);
|
|
55
|
-
select is(
|
|
56
|
-
(
|
|
57
|
-
select count(*)::INT
|
|
58
|
-
from pgmq.a_sequential
|
|
59
|
-
where message ->> 'step_slug' = 'second'
|
|
60
|
-
limit 1
|
|
61
|
-
),
|
|
62
|
-
0::INT,
|
|
63
|
-
'The other message should not be archived'
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
select finish();
|
|
67
|
-
rollback;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(4);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- Start the flow
|
|
7
|
-
select pgflow.start_flow('sequential', '{"test": true}'::JSONB);
|
|
8
|
-
|
|
9
|
-
-- TEST: Initial remaining_steps should be 3 and status should be 'started'
|
|
10
|
-
select results_eq(
|
|
11
|
-
$$ SELECT remaining_steps::int, status FROM pgflow.runs LIMIT 1 $$,
|
|
12
|
-
$$ VALUES (3::int, 'started'::text) $$,
|
|
13
|
-
'Initial remaining_steps should be 3 and status should be started'
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- Complete the first step's task
|
|
17
|
-
select pgflow.complete_task(
|
|
18
|
-
(select run_id from pgflow.runs limit 1),
|
|
19
|
-
'first',
|
|
20
|
-
0,
|
|
21
|
-
'"first was successful"'::JSONB
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
-- TEST: After completing first step, remaining_steps should be 2 and status still 'started'
|
|
25
|
-
select results_eq(
|
|
26
|
-
$$ SELECT remaining_steps::int, status FROM pgflow.runs LIMIT 1 $$,
|
|
27
|
-
$$ VALUES (2::int, 'started'::text) $$,
|
|
28
|
-
'After completing first step, remaining_steps should be 2 and status still started'
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
-- Complete the second step's task
|
|
32
|
-
select pgflow.complete_task(
|
|
33
|
-
(select run_id from pgflow.runs limit 1),
|
|
34
|
-
'second',
|
|
35
|
-
0,
|
|
36
|
-
'"second was successful"'::JSONB
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
-- TEST: After completing second step, remaining_steps should be 1 and status still 'started'
|
|
40
|
-
select results_eq(
|
|
41
|
-
$$ SELECT remaining_steps::int, status FROM pgflow.runs LIMIT 1 $$,
|
|
42
|
-
$$ VALUES (1::int, 'started'::text) $$,
|
|
43
|
-
'After completing second step, remaining_steps should be 1 and status still started'
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
-- Complete the last step's task
|
|
47
|
-
select pgflow.complete_task(
|
|
48
|
-
(select run_id from pgflow.runs limit 1),
|
|
49
|
-
'last',
|
|
50
|
-
0,
|
|
51
|
-
'"last was successful"'::JSONB
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
-- TEST: Final remaining_steps should be 0 and status should be 'completed'
|
|
55
|
-
select results_eq(
|
|
56
|
-
$$ SELECT remaining_steps::int, status FROM pgflow.runs LIMIT 1 $$,
|
|
57
|
-
$$ VALUES (0::int, 'completed'::text) $$,
|
|
58
|
-
'Final remaining_steps should be 0 and status should be completed'
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
select finish();
|
|
62
|
-
rollback;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(5);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- Start a flow run
|
|
7
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- Complete the first task
|
|
10
|
-
select pgflow.complete_task(
|
|
11
|
-
(select run_id from pgflow.runs limit 1),
|
|
12
|
-
'first',
|
|
13
|
-
0,
|
|
14
|
-
'{"result": "first completed"}'::jsonb
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- TEST: Task should be marked as completed with correct output
|
|
18
|
-
select results_eq(
|
|
19
|
-
$$ SELECT status, output FROM pgflow.step_tasks
|
|
20
|
-
WHERE run_id = (SELECT run_id FROM pgflow.runs LIMIT 1)
|
|
21
|
-
AND step_slug = 'first' AND task_index = 0 $$,
|
|
22
|
-
$$ VALUES ('completed', '{"result": "first completed"}'::jsonb) $$,
|
|
23
|
-
'Task should be marked as completed with correct output'
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
-- TEST: Step state should be marked as completed
|
|
27
|
-
select results_eq(
|
|
28
|
-
$$ SELECT status, remaining_tasks FROM pgflow.step_states
|
|
29
|
-
WHERE run_id = (SELECT run_id FROM pgflow.runs LIMIT 1)
|
|
30
|
-
AND step_slug = 'first' $$,
|
|
31
|
-
$$ VALUES ('completed', 0) $$,
|
|
32
|
-
'Step state should be marked as completed with no remaining tasks'
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
-- TEST: Dependent step should have remaining_deps decremented
|
|
36
|
-
select results_eq(
|
|
37
|
-
$$ SELECT remaining_deps FROM pgflow.step_states
|
|
38
|
-
WHERE run_id = (SELECT run_id FROM pgflow.runs LIMIT 1)
|
|
39
|
-
AND step_slug = 'second' $$,
|
|
40
|
-
$$ VALUES (0) $$,
|
|
41
|
-
'Dependent step should have remaining_deps decremented to 0'
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
-- TEST: Dependent step task should be created and queued
|
|
45
|
-
select results_eq(
|
|
46
|
-
$$ SELECT status FROM pgflow.step_tasks
|
|
47
|
-
WHERE run_id = (SELECT run_id FROM pgflow.runs LIMIT 1)
|
|
48
|
-
AND step_slug = 'second' $$,
|
|
49
|
-
$$ VALUES ('queued') $$,
|
|
50
|
-
'Dependent step task should be created and queued'
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
-- TEST: Message should be in the queue for the dependent step
|
|
54
|
-
select is(
|
|
55
|
-
(
|
|
56
|
-
select count(*)::int from pgmq.q_sequential
|
|
57
|
-
where message ->> 'step_slug' = 'second'
|
|
58
|
-
),
|
|
59
|
-
1::int,
|
|
60
|
-
'Message should be in the queue for the dependent step'
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
select finish();
|
|
64
|
-
rollback;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(4);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- Start the flow
|
|
7
|
-
select pgflow.start_flow('sequential', '{"test": true}'::JSONB);
|
|
8
|
-
|
|
9
|
-
-- TEST: Initial remaining_steps should be 3
|
|
10
|
-
select is(
|
|
11
|
-
(select remaining_steps::INT from pgflow.runs limit 1),
|
|
12
|
-
3::INT,
|
|
13
|
-
'Initial remaining_steps should be 3'
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- Complete the first step's task
|
|
17
|
-
select pgflow.complete_task(
|
|
18
|
-
(select run_id from pgflow.runs limit 1),
|
|
19
|
-
'first',
|
|
20
|
-
0,
|
|
21
|
-
'{"result": "success"}'::JSONB
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
-- TEST: After completing first step, remaining_steps should be 2
|
|
25
|
-
select is(
|
|
26
|
-
(select remaining_steps::INT from pgflow.runs limit 1),
|
|
27
|
-
2::INT,
|
|
28
|
-
'After completing first step, remaining_steps should be 2'
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
-- Complete the second step's task
|
|
32
|
-
select pgflow.complete_task(
|
|
33
|
-
(select run_id from pgflow.runs limit 1),
|
|
34
|
-
'second',
|
|
35
|
-
0,
|
|
36
|
-
'{"result": "success"}'::JSONB
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
-- TEST: After completing second step, remaining_steps should be 1
|
|
40
|
-
select is(
|
|
41
|
-
(select remaining_steps::INT from pgflow.runs limit 1),
|
|
42
|
-
1::INT,
|
|
43
|
-
'After completing second step, remaining_steps should be 1'
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
-- Complete the last step's task
|
|
47
|
-
select pgflow.complete_task(
|
|
48
|
-
(select run_id from pgflow.runs limit 1),
|
|
49
|
-
'last',
|
|
50
|
-
0,
|
|
51
|
-
'{"result": "success"}'::JSONB
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
-- TEST: Final remaining_steps should be 0
|
|
55
|
-
select is(
|
|
56
|
-
(select remaining_steps::INT from pgflow.runs limit 1),
|
|
57
|
-
0::INT,
|
|
58
|
-
'Final remaining_steps should be 0'
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
select finish();
|
|
62
|
-
rollback;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('two_roots_left_right');
|
|
5
|
-
|
|
6
|
-
-- Start the flow
|
|
7
|
-
select pgflow.start_flow('two_roots_left_right', '"hello"'::JSONB);
|
|
8
|
-
|
|
9
|
-
-- Complete all the steps
|
|
10
|
-
select pgflow.complete_task(
|
|
11
|
-
(select run_id from pgflow.runs limit 1),
|
|
12
|
-
'connected_root',
|
|
13
|
-
0,
|
|
14
|
-
'"root successful"'::JSONB
|
|
15
|
-
);
|
|
16
|
-
select pgflow.complete_task(
|
|
17
|
-
(select run_id from pgflow.runs limit 1),
|
|
18
|
-
'left',
|
|
19
|
-
0,
|
|
20
|
-
'"left successful"'::JSONB
|
|
21
|
-
);
|
|
22
|
-
select pgflow.complete_task(
|
|
23
|
-
(select run_id from pgflow.runs limit 1),
|
|
24
|
-
'right',
|
|
25
|
-
0,
|
|
26
|
-
'"right successful"'::JSONB
|
|
27
|
-
);
|
|
28
|
-
select pgflow.complete_task(
|
|
29
|
-
(select run_id from pgflow.runs limit 1),
|
|
30
|
-
'disconnected_root',
|
|
31
|
-
0,
|
|
32
|
-
'"disconnected successful"'::JSONB
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
-- TEST: Make sure that run is completed
|
|
36
|
-
select results_eq(
|
|
37
|
-
$$ SELECT status::text, remaining_steps::int FROM pgflow.runs LIMIT 1 $$,
|
|
38
|
-
$$ VALUES ('completed'::text, 0::int) $$,
|
|
39
|
-
'Run was completed'
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
-- noqa: disable=all
|
|
43
|
-
PREPARE expected_output AS SELECT
|
|
44
|
-
jsonb_build_object(
|
|
45
|
-
'disconnected_root', '"disconnected successful"'::JSONB,
|
|
46
|
-
'left', '"left successful"'::JSONB,
|
|
47
|
-
'right', '"right successful"'::JSONB
|
|
48
|
-
);
|
|
49
|
-
-- noqa: enable=all
|
|
50
|
-
SELECT results_eq (
|
|
51
|
-
$$ SELECT output FROM pgflow.runs LIMIT 1 $$,
|
|
52
|
-
'expected_output',
|
|
53
|
-
'Outputs of all final steps were saved as run output'
|
|
54
|
-
) ;
|
|
55
|
-
|
|
56
|
-
SELECT finish () ;
|
|
57
|
-
ROLLBACK ;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Clean up any existing test queue
|
|
6
|
-
select pgmq.drop_queue('test_flow')
|
|
7
|
-
from pgmq.list_queues()
|
|
8
|
-
where queue_name = 'test_flow'
|
|
9
|
-
limit 1;
|
|
10
|
-
|
|
11
|
-
-- TEST: Flow should be added to the flows table
|
|
12
|
-
select pgflow.create_flow('test_flow');
|
|
13
|
-
select results_eq(
|
|
14
|
-
$$ SELECT flow_slug FROM pgflow.flows $$,
|
|
15
|
-
array['test_flow']::text [],
|
|
16
|
-
'Flow should be added to the flows table'
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
-- TEST: Creating a flow should create a PGMQ queue with the same name
|
|
20
|
-
select results_eq(
|
|
21
|
-
$$ SELECT EXISTS(SELECT 1 FROM pgmq.list_queues() WHERE queue_name = 'test_flow') $$,
|
|
22
|
-
array[true],
|
|
23
|
-
'Creating a flow should create a PGMQ queue with the same name'
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
select * from finish();
|
|
27
|
-
rollback;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup initial flow
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
|
|
8
|
-
-- SETUP: Create flow again to ensure it doesn't throw
|
|
9
|
-
select pgflow.create_flow('test_flow');
|
|
10
|
-
|
|
11
|
-
-- TEST: No duplicate flow should be created
|
|
12
|
-
select results_eq(
|
|
13
|
-
$$ SELECT flow_slug FROM pgflow.flows $$,
|
|
14
|
-
array['test_flow']::text [],
|
|
15
|
-
'No duplicate flow should be created'
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
--TEST: Creating a flow with existing flow_slug should still return the flow
|
|
19
|
-
select results_eq(
|
|
20
|
-
$$ SELECT flow_slug FROM pgflow.create_flow('test_flow') $$,
|
|
21
|
-
$$ VALUES ('test_flow') $$,
|
|
22
|
-
'Creating a flow with existing flow_slug should still return the flow'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
select * from finish();
|
|
26
|
-
rollback;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- TEST: Should detect and prevent invalid flow slug
|
|
6
|
-
select throws_ok(
|
|
7
|
-
$$ SELECT pgflow.create_flow('invalid-flow') $$,
|
|
8
|
-
'new row for relation "flows" violates check constraint "slug_is_valid"',
|
|
9
|
-
'Should detect and prevent invalid flow slug'
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
select * from finish();
|
|
13
|
-
rollback;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(5);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- SETUP: flow with all default values
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
|
|
8
|
-
--TEST: Should create flow with default max_attempts, base_delay and timeout
|
|
9
|
-
select results_eq(
|
|
10
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.create_flow('test_flow') $$,
|
|
11
|
-
$$ VALUES (3, 5, 60) $$,
|
|
12
|
-
'Should create flow with default opt_max_attempts, opt_base_delay and opt_timeout'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
-- SETUP: flow with overriden max_attempts
|
|
16
|
-
select pgflow.create_flow('test_flow_2', max_attempts => 10);
|
|
17
|
-
|
|
18
|
-
--TEST: Should allow overriding opt_max_attempts
|
|
19
|
-
select results_eq(
|
|
20
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.create_flow('test_flow_2') $$,
|
|
21
|
-
$$ VALUES (10, 5, 60) $$,
|
|
22
|
-
'Should allow overriding opt_max_attempts'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
-- SETUP: flow with overriden opt_base_delay
|
|
26
|
-
select pgflow.create_flow('test_flow_3', base_delay => 10);
|
|
27
|
-
|
|
28
|
-
--TEST: Should allow overriding base_delay
|
|
29
|
-
select results_eq(
|
|
30
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.create_flow('test_flow_3') $$,
|
|
31
|
-
$$ VALUES (3, 10, 60) $$,
|
|
32
|
-
'Should allow overriding opt_base_delay'
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
-- SETUP: flow with overriden opt_timeout
|
|
36
|
-
select pgflow.create_flow('test_flow_5', timeout => 7200);
|
|
37
|
-
|
|
38
|
-
--TEST: Should allow overriding timeout
|
|
39
|
-
select results_eq(
|
|
40
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.create_flow('test_flow_5') $$,
|
|
41
|
-
$$ VALUES (3, 5, 7200) $$,
|
|
42
|
-
'Should allow overriding opt_timeout'
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
-- SETUP: create same flow again to make sure it doesnt get updated
|
|
46
|
-
select pgflow.create_flow('test_flow_4', max_attempts => 10, base_delay => 15, timeout => 30);
|
|
47
|
-
select pgflow.create_flow('test_flow_4', max_attempts => 20, base_delay => 30, timeout => 60);
|
|
48
|
-
|
|
49
|
-
--TEST: Should not update opt_max_attempts, opt_base_delay and opt_timeout
|
|
50
|
-
select results_eq(
|
|
51
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.create_flow('test_flow_4') $$,
|
|
52
|
-
$$ VALUES (10, 15, 30) $$,
|
|
53
|
-
'Should not update opt_max_attempts, opt_base_delay and opt_timeout'
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
select * from finish();
|
|
57
|
-
rollback;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(4);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- create a test flow with two steps that have different base delays
|
|
6
|
-
select pgflow.create_flow('backoff_test');
|
|
7
|
-
select pgflow.add_step('backoff_test', 'first', max_attempts => 3, base_delay => 1);
|
|
8
|
-
select pgflow.add_step('backoff_test', 'last', max_attempts => 4, base_delay => 2);
|
|
9
|
-
|
|
10
|
-
-- start the flow with test data
|
|
11
|
-
select pgflow.start_flow('backoff_test', '{"test": true}'::jsonb);
|
|
12
|
-
|
|
13
|
-
-- simulate a task failure
|
|
14
|
-
select pgflow_tests.poll_and_fail('backoff_test', 1, 1);
|
|
15
|
-
|
|
16
|
-
-- make the message immediately visible (bypassing the retry delay)
|
|
17
|
-
select pgflow_tests.reset_message_visibility('backoff_test');
|
|
18
|
-
|
|
19
|
-
-- simulate a task failure
|
|
20
|
-
select pgflow_tests.poll_and_fail('backoff_test', 1, 1);
|
|
21
|
-
|
|
22
|
-
-- TEST: make sure we have proper attempts_count
|
|
23
|
-
select is(
|
|
24
|
-
(select attempts_count::int from pgflow.step_tasks where step_slug = 'first'),
|
|
25
|
-
2::int,
|
|
26
|
-
'first task should have 2 attempts'
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
-- TEST: verify exponential backoff is set properly
|
|
30
|
-
select is(
|
|
31
|
-
(select vt_seconds from pgflow_tests.message_timing('first', 'backoff_test') limit 1),
|
|
32
|
-
pgflow.calculate_retry_delay(1, 2),
|
|
33
|
-
'first step task should have visible time set to at least the base delay'
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
-- SETUP: proceed to next step
|
|
37
|
-
select pgflow_tests.reset_message_visibility('backoff_test');
|
|
38
|
-
select pgflow_tests.poll_and_complete('backoff_test', 1, 1);
|
|
39
|
-
select pgflow_tests.reset_message_visibility('backoff_test');
|
|
40
|
-
|
|
41
|
-
-- SETUP: fail twice to verify appropriate backoff
|
|
42
|
-
select pgflow_tests.poll_and_fail('backoff_test', 1, 1);
|
|
43
|
-
select pgflow_tests.reset_message_visibility('backoff_test');
|
|
44
|
-
select pgflow_tests.poll_and_fail('backoff_test', 1, 1);
|
|
45
|
-
select pgflow_tests.reset_message_visibility('backoff_test');
|
|
46
|
-
select pgflow_tests.poll_and_fail('backoff_test', 1, 1);
|
|
47
|
-
--
|
|
48
|
-
-- TEST: make sure we have proper attempts_count
|
|
49
|
-
select is(
|
|
50
|
-
(select attempts_count from pgflow.step_tasks where step_slug = 'last'),
|
|
51
|
-
3,
|
|
52
|
-
'last task should have 3 attempts'
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
-- TEST: verify exponential backoff is set properly
|
|
56
|
-
select pgflow_tests.assert_retry_delay(
|
|
57
|
-
queue_name => 'backoff_test',
|
|
58
|
-
step_slug => 'last',
|
|
59
|
-
expected_delay => pgflow.calculate_retry_delay(2, 3),
|
|
60
|
-
description => 'last step task should have visible time set to at least the base delay'
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
-- select is(
|
|
64
|
-
-- (select vt_seconds from pgflow_tests.message_timing('last', 'backoff_test') limit 1),
|
|
65
|
-
-- pgflow.calculate_retry_delay(2, 3),
|
|
66
|
-
-- 'last step task should have visible time set to at least the base delay'
|
|
67
|
-
-- );
|
|
68
|
-
|
|
69
|
-
select finish();
|
|
70
|
-
rollback;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(5);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- SETUP
|
|
6
|
-
select pgflow.create_flow('with_retry');
|
|
7
|
-
select pgflow.add_step('with_retry', 'first', max_attempts => 0, base_delay => 0);
|
|
8
|
-
select pgflow.start_flow('with_retry', '{"test": true}'::JSONB);
|
|
9
|
-
|
|
10
|
-
-- max_attempts is 0, so failing once should mark the task as failed
|
|
11
|
-
select pgflow_tests.poll_and_fail('with_retry');
|
|
12
|
-
|
|
13
|
-
-- TEST: The task should be queued
|
|
14
|
-
select is(
|
|
15
|
-
(select status from pgflow.step_tasks where flow_slug = 'with_retry' and step_slug = 'first'),
|
|
16
|
-
'failed',
|
|
17
|
-
'The task should be failed'
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
-- TEST: The task should have null error_message
|
|
21
|
-
select is(
|
|
22
|
-
(select error_message from pgflow.step_tasks where flow_slug = 'with_retry' and step_slug = 'first'),
|
|
23
|
-
'first FAILED',
|
|
24
|
-
'The task should have attempts_count incremented'
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
-- TEST: The task's message should be in the queue
|
|
28
|
-
select is(
|
|
29
|
-
(select count(*)::INT from pgmq.q_with_retry),
|
|
30
|
-
0,
|
|
31
|
-
'There should be no messages in the queue'
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
-- TEST: The step should be marked as failed
|
|
35
|
-
select is(
|
|
36
|
-
(select status from pgflow.step_states where flow_slug = 'with_retry' and step_slug = 'first' limit 1),
|
|
37
|
-
'failed',
|
|
38
|
-
'The step should be marked as failed'
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
-- TEST: The run should be marked as failed
|
|
42
|
-
select is(
|
|
43
|
-
(select status from pgflow.runs where flow_slug = 'with_retry' limit 1),
|
|
44
|
-
'failed',
|
|
45
|
-
'The run should be marked as failed'
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
select finish();
|
|
49
|
-
rollback;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- SETUP: Create a flow with custom retry settings
|
|
6
|
-
select pgflow.create_flow('custom_retry', max_attempts => 2, base_delay => 0);
|
|
7
|
-
select pgflow.add_step('custom_retry', 'test_step');
|
|
8
|
-
|
|
9
|
-
-- Start the flow
|
|
10
|
-
select pgflow.start_flow('custom_retry', '{"test": true}'::JSONB);
|
|
11
|
-
|
|
12
|
-
-- Fail the task first time
|
|
13
|
-
select pgflow_tests.poll_and_fail('custom_retry');
|
|
14
|
-
|
|
15
|
-
-- TEST: The task should be queued (first retry)
|
|
16
|
-
select is(
|
|
17
|
-
(select status from pgflow.step_tasks limit 1),
|
|
18
|
-
'queued',
|
|
19
|
-
'Task should be queued after first failure (1st attempt of 2)'
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
-- Fail the task second time
|
|
23
|
-
select pgflow_tests.poll_and_fail('custom_retry');
|
|
24
|
-
|
|
25
|
-
-- TEST: The task should be queued (second retry)
|
|
26
|
-
select is(
|
|
27
|
-
(
|
|
28
|
-
select status from pgflow.step_tasks
|
|
29
|
-
where
|
|
30
|
-
run_id = (select run_id from pgflow.runs where flow_slug = 'custom_retry')
|
|
31
|
-
and step_slug = 'test_step'
|
|
32
|
-
),
|
|
33
|
-
'failed',
|
|
34
|
-
'Task should be failed after second failure (2nd attempt of 2)'
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
-- TEST: The run should be failed
|
|
38
|
-
select is(
|
|
39
|
-
(
|
|
40
|
-
select status from pgflow.runs
|
|
41
|
-
where flow_slug = 'custom_retry'
|
|
42
|
-
),
|
|
43
|
-
'failed',
|
|
44
|
-
'Run should be failed after exceeding retry limit'
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
select finish();
|
|
48
|
-
rollback;
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- SETUP: Create a flow with custom retry settings
|
|
6
|
-
select pgflow.create_flow('custom_retry', max_attempts => 10, base_delay => 10);
|
|
7
|
-
select pgflow.add_step('custom_retry', 'test_step', max_attempts => 2, base_delay => 0);
|
|
8
|
-
|
|
9
|
-
-- Start the flow
|
|
10
|
-
select pgflow.start_flow('custom_retry', '{"test": true}'::JSONB);
|
|
11
|
-
|
|
12
|
-
-- Fail the task first time
|
|
13
|
-
select pgflow_tests.poll_and_fail('custom_retry');
|
|
14
|
-
|
|
15
|
-
-- TEST: The task should be queued (first retry)
|
|
16
|
-
select is(
|
|
17
|
-
(select status from pgflow.step_tasks limit 1),
|
|
18
|
-
'queued',
|
|
19
|
-
'Task should be queued after first failure (1st attempt of 2)'
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
-- Fail the task second time
|
|
23
|
-
select pgflow_tests.poll_and_fail('custom_retry');
|
|
24
|
-
|
|
25
|
-
-- TEST: The task should be queued (second retry)
|
|
26
|
-
select is(
|
|
27
|
-
(
|
|
28
|
-
select status from pgflow.step_tasks
|
|
29
|
-
where
|
|
30
|
-
run_id = (select run_id from pgflow.runs where flow_slug = 'custom_retry')
|
|
31
|
-
and step_slug = 'test_step'
|
|
32
|
-
),
|
|
33
|
-
'failed',
|
|
34
|
-
'Task should be failed after second failure (2nd attempt of 2)'
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
-- TEST: The run should be failed
|
|
38
|
-
select is(
|
|
39
|
-
(
|
|
40
|
-
select status from pgflow.runs
|
|
41
|
-
where flow_slug = 'custom_retry'
|
|
42
|
-
),
|
|
43
|
-
'failed',
|
|
44
|
-
'Run should be failed after exceeding retry limit'
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
select finish();
|
|
48
|
-
rollback;
|