@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,39 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(4);
|
|
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
|
-
select pgflow_tests.poll_and_fail('sequential');
|
|
9
|
-
|
|
10
|
-
-- TEST: The task should be queued
|
|
11
|
-
select is(
|
|
12
|
-
(select status from pgflow.step_tasks where flow_slug = 'sequential' and step_slug = 'first'),
|
|
13
|
-
'queued',
|
|
14
|
-
'The task should be queued'
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- TEST: The task should have attempts_count incremented
|
|
18
|
-
select is(
|
|
19
|
-
(select attempts_count from pgflow.step_tasks where flow_slug = 'sequential' and step_slug = 'first'),
|
|
20
|
-
1,
|
|
21
|
-
'The task should have attempts_count incremented'
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
-- TEST: The task should have null error_message
|
|
25
|
-
select is(
|
|
26
|
-
(select error_message from pgflow.step_tasks where flow_slug = 'sequential' and step_slug = 'first'),
|
|
27
|
-
'first FAILED',
|
|
28
|
-
'The task should have attempts_count incremented'
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
-- TEST: The task's message should be in the queue
|
|
32
|
-
select is(
|
|
33
|
-
(select message ->> 'step_slug' from pgmq.q_sequential limit 1),
|
|
34
|
-
'first',
|
|
35
|
-
'The task''s message should be in the queue'
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
select finish();
|
|
39
|
-
rollback;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(11);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- TEST: Null input
|
|
6
|
-
select ok(
|
|
7
|
-
not pgflow.is_valid_slug(null),
|
|
8
|
-
'is_valid_slug returns false for NULL input'
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
-- TEST: Empty string
|
|
12
|
-
select ok(
|
|
13
|
-
not pgflow.is_valid_slug(''),
|
|
14
|
-
'is_valid_slug returns false for empty string'
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
-- TEST: Too long string (128+ chars)
|
|
18
|
-
select ok(
|
|
19
|
-
not pgflow.is_valid_slug(repeat('x', 129)),
|
|
20
|
-
'is_valid_slug returns false for strings longer than 128 chars'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
-- TEST: String with dashes
|
|
24
|
-
select ok(
|
|
25
|
-
not pgflow.is_valid_slug('test-slug'),
|
|
26
|
-
'is_valid_slug returns false for strings with dashes'
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
-- TEST: String with spaces
|
|
30
|
-
select ok(
|
|
31
|
-
not pgflow.is_valid_slug('test slug'),
|
|
32
|
-
'is_valid_slug returns false for strings with spaces'
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
-- TEST: String starting with number
|
|
36
|
-
select ok(
|
|
37
|
-
not pgflow.is_valid_slug('123test'),
|
|
38
|
-
'is_valid_slug returns false for strings starting with numbers'
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
-- TEST: Valid single word
|
|
42
|
-
select ok(
|
|
43
|
-
pgflow.is_valid_slug('valid'),
|
|
44
|
-
'is_valid_slug returns true for single word'
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
-- TEST: Valid with underscore
|
|
48
|
-
select ok(
|
|
49
|
-
pgflow.is_valid_slug('valid_slug'),
|
|
50
|
-
'is_valid_slug returns true for string with underscore'
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
-- TEST: Valid with numbers (not at start)
|
|
54
|
-
select ok(
|
|
55
|
-
pgflow.is_valid_slug('valid123'),
|
|
56
|
-
'is_valid_slug returns true for string with numbers not at start'
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
-- TEST: Valid mixed case
|
|
60
|
-
select ok(
|
|
61
|
-
pgflow.is_valid_slug('validSlug'),
|
|
62
|
-
'is_valid_slug returns true for mixed case string'
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
-- TEST:
|
|
66
|
-
select ok(
|
|
67
|
-
not pgflow.is_valid_slug('run'),
|
|
68
|
-
'is_valid_slug returns false for reserved word'
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
select finish();
|
|
72
|
-
rollback;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('two_roots');
|
|
5
|
-
|
|
6
|
-
-- Start the flow and complete the root steps
|
|
7
|
-
select pgflow.start_flow('two_roots', '"root input"'::jsonb);
|
|
8
|
-
select pgflow.poll_for_tasks('two_roots', 1, 2);
|
|
9
|
-
select pgflow.complete_task(
|
|
10
|
-
(select run_id from pgflow.runs limit 1),
|
|
11
|
-
'root_a',
|
|
12
|
-
0,
|
|
13
|
-
'"root_a output"'::jsonb
|
|
14
|
-
);
|
|
15
|
-
select pgflow.complete_task(
|
|
16
|
-
(select run_id from pgflow.runs limit 1),
|
|
17
|
-
'root_b',
|
|
18
|
-
0,
|
|
19
|
-
'"root_b output"'::jsonb
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
-- TEST: Verify that the queued message have the proper input
|
|
23
|
-
select is(
|
|
24
|
-
(select input from pgflow.poll_for_tasks('two_roots', 1, 1)),
|
|
25
|
-
jsonb_build_object(
|
|
26
|
-
'run', 'root input',
|
|
27
|
-
'root_a', 'root_a output',
|
|
28
|
-
'root_b', 'root_b output'
|
|
29
|
-
)
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
select finish();
|
|
33
|
-
rollback;
|
|
34
|
-
|
|
35
|
-
select '"yolox"'::jsonb @> '"yolo"'::jsonb;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run which will put a single task in the queue
|
|
7
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- TEST: Poll a single task with big visibility timeout (vt = 10)
|
|
10
|
-
select is(
|
|
11
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
12
|
-
queue_name => 'sequential'::text,
|
|
13
|
-
vt => 5,
|
|
14
|
-
qty => 1,
|
|
15
|
-
max_poll_seconds => 1
|
|
16
|
-
)),
|
|
17
|
-
1::integer,
|
|
18
|
-
'First poll should get the available task'
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
-- TEST: Immediate second poll (simulating concurrent access) should get nothing
|
|
22
|
-
-- because the message is hidden with vt=5
|
|
23
|
-
select is(
|
|
24
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
25
|
-
queue_name => 'sequential'::text,
|
|
26
|
-
vt => 5,
|
|
27
|
-
qty => 1,
|
|
28
|
-
max_poll_seconds => 1
|
|
29
|
-
)),
|
|
30
|
-
0::integer,
|
|
31
|
-
'Concurrent poll should not get the same task (due to visibility timeout)'
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
select * from finish();
|
|
35
|
-
rollback;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
select pgflow.create_flow('simple', max_attempts => 3, base_delay => 0);
|
|
6
|
-
select pgflow.add_step('simple', 'first');
|
|
7
|
-
select pgflow.add_step('simple', 'last');
|
|
8
|
-
select pgflow.start_flow('simple', '"hello"'::jsonb);
|
|
9
|
-
|
|
10
|
-
-- SETUP: poll twice, first fialing them completing
|
|
11
|
-
select pgflow_tests.poll_and_fail('simple', 1, 1);
|
|
12
|
-
select pgflow_tests.poll_and_complete('simple', 1, 1);
|
|
13
|
-
|
|
14
|
-
-- TEST: polling increments, regardless of failure/completion
|
|
15
|
-
select is(
|
|
16
|
-
(select attempts_count::int from pgflow.step_tasks where step_slug = 'first'),
|
|
17
|
-
2,
|
|
18
|
-
'Polling a task should increment its attempts_count, regardless of status'
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
-- SETUP:
|
|
22
|
-
select pgflow_tests.poll_and_fail('simple', 1, 1);
|
|
23
|
-
select pgflow_tests.poll_and_fail('simple', 1, 1);
|
|
24
|
-
select pgflow_tests.poll_and_fail('simple', 1, 1);
|
|
25
|
-
|
|
26
|
-
-- TEST: polling increments, regardless of failure/completion
|
|
27
|
-
select is(
|
|
28
|
-
(select attempts_count::int from pgflow.step_tasks where step_slug = 'last'),
|
|
29
|
-
3,
|
|
30
|
-
'Polling a task should increment its attempts_count'
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
select finish();
|
|
35
|
-
rollback;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start multiple flow runs which will put multiple tasks in the queue
|
|
7
|
-
select pgflow.start_flow('sequential', '{"id": 1}'::jsonb);
|
|
8
|
-
select pgflow.start_flow('sequential', '{"id": 2}'::jsonb);
|
|
9
|
-
select pgflow.start_flow('sequential', '{"id": 3}'::jsonb);
|
|
10
|
-
|
|
11
|
-
-- TEST: Poll multiple tasks at once (qty = 3)
|
|
12
|
-
select is(
|
|
13
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
14
|
-
queue_name => 'sequential'::text,
|
|
15
|
-
vt => 5,
|
|
16
|
-
qty => 3,
|
|
17
|
-
max_poll_seconds => 1
|
|
18
|
-
)),
|
|
19
|
-
3::integer,
|
|
20
|
-
'Should return 3 tasks when qty=3 and 3 tasks are available'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
select finish();
|
|
24
|
-
rollback;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- This is a regression test for a bug that was showing up when messages
|
|
7
|
-
-- were not archived properly after being completed
|
|
8
|
-
-- It manifested as completed tasks being updated to 'started'
|
|
9
|
-
|
|
10
|
-
-- SETUP: Start a flow, poll and complete the first task
|
|
11
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
12
|
-
select pgflow.poll_for_tasks('sequential'::text, 0, 1);
|
|
13
|
-
select pgflow.complete_task(
|
|
14
|
-
(
|
|
15
|
-
select run_id
|
|
16
|
-
from pgflow.runs
|
|
17
|
-
where flow_slug = 'sequential'
|
|
18
|
-
order by run_id
|
|
19
|
-
limit 1
|
|
20
|
-
),
|
|
21
|
-
'first',
|
|
22
|
-
0,
|
|
23
|
-
'"first completed"'::jsonb
|
|
24
|
-
);
|
|
25
|
-
select pgflow.poll_for_tasks('sequential'::text, 0, 1);
|
|
26
|
-
|
|
27
|
-
-- TEST: Already completed tasks should not be changed
|
|
28
|
-
select is(
|
|
29
|
-
(select status from pgflow.step_tasks where step_slug = 'first'),
|
|
30
|
-
'completed',
|
|
31
|
-
'Already completed task should not be changed'
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
select finish();
|
|
35
|
-
rollback;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run
|
|
7
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- Prepare the actual query
|
|
10
|
-
PREPARE actual AS
|
|
11
|
-
SELECT flow_slug, run_id, step_slug, input, msg_id
|
|
12
|
-
FROM pgflow.poll_for_tasks (
|
|
13
|
-
queue_name => 'sequential',
|
|
14
|
-
vt => 1,
|
|
15
|
-
qty => 1
|
|
16
|
-
)
|
|
17
|
-
LIMIT 1 ;
|
|
18
|
-
|
|
19
|
-
-- Prepare the expected result
|
|
20
|
-
PREPARE expected AS
|
|
21
|
-
SELECT 'sequential'::text AS flow_slug,
|
|
22
|
-
(SELECT run_id FROM pgflow.runs WHERE flow_slug = 'sequential' LIMIT 1) AS run_id,
|
|
23
|
-
'first'::text AS step_slug,
|
|
24
|
-
jsonb_build_object ('run', 'hello')::jsonb AS input,
|
|
25
|
-
(SELECT message_id FROM pgflow.step_tasks
|
|
26
|
-
WHERE flow_slug = 'sequential'
|
|
27
|
-
AND step_slug = 'first'
|
|
28
|
-
LIMIT 1) AS msg_id ;
|
|
29
|
-
|
|
30
|
-
-- Compare the results
|
|
31
|
-
SELECT results_eq (
|
|
32
|
-
'actual',
|
|
33
|
-
'expected',
|
|
34
|
-
'poll_for_tasks() returns the expected worker task'
|
|
35
|
-
) ;
|
|
36
|
-
|
|
37
|
-
SELECT finish () ;
|
|
38
|
-
ROLLBACK ;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run which will put a task in the queue
|
|
7
|
-
select * from pgflow.start_flow('sequential', '{"id": 1}'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- Manually delete a step_task but keep the message in the queue
|
|
10
|
-
-- This simulates an inconsistent state where a message exists
|
|
11
|
-
-- but there's no corresponding step_task
|
|
12
|
-
delete from pgflow.step_tasks
|
|
13
|
-
where
|
|
14
|
-
run_id = (
|
|
15
|
-
select run_id from pgflow.runs
|
|
16
|
-
where flow_slug = 'sequential' limit 1
|
|
17
|
-
)
|
|
18
|
-
and step_slug = 'first';
|
|
19
|
-
|
|
20
|
-
-- TEST: Polling should not return tasks for missing step_tasks
|
|
21
|
-
-- even though messages might exist in the queue
|
|
22
|
-
select is(
|
|
23
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
24
|
-
queue_name => 'sequential'::text,
|
|
25
|
-
vt => 5,
|
|
26
|
-
qty => 1,
|
|
27
|
-
max_poll_seconds => 1
|
|
28
|
-
)),
|
|
29
|
-
0::integer,
|
|
30
|
-
'Should not return tasks when step_tasks row is missing'
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
select * from finish();
|
|
34
|
-
rollback;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- TEST: Polling from an empty queue returns no tasks
|
|
7
|
-
select is(
|
|
8
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
9
|
-
queue_name => 'sequential'::text,
|
|
10
|
-
vt => 5,
|
|
11
|
-
qty => 10,
|
|
12
|
-
max_poll_seconds => 1
|
|
13
|
-
)),
|
|
14
|
-
0::integer,
|
|
15
|
-
'Should return no tasks when queue is empty'
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
select * from finish();
|
|
19
|
-
rollback;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run which will put a task in the queue
|
|
7
|
-
select pgflow.start_flow('sequential', '{"id": 1}'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- TEST: Calling with qty = 0 should return no tasks
|
|
10
|
-
select is(
|
|
11
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
12
|
-
queue_name => 'sequential'::text,
|
|
13
|
-
vt => 5,
|
|
14
|
-
qty => 0,
|
|
15
|
-
max_poll_seconds => 1
|
|
16
|
-
)),
|
|
17
|
-
0::integer,
|
|
18
|
-
'Should return no tasks when qty=0'
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
select * from finish();
|
|
22
|
-
rollback;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Create a flow with two root steps, each with different opt_timeout values
|
|
6
|
-
select pgflow.create_flow('timeout_test', timeout => 60);
|
|
7
|
-
select pgflow.add_step('timeout_test', 'step_with_flow_timeout');
|
|
8
|
-
select pgflow.add_step('timeout_test', 'step_30', timeout => 30);
|
|
9
|
-
select pgflow.add_step('timeout_test', 'step_45', timeout => 45);
|
|
10
|
-
|
|
11
|
-
-- Start the flow which will create tasks for both root steps
|
|
12
|
-
select pgflow.start_flow('timeout_test', '"test_input"'::jsonb);
|
|
13
|
-
|
|
14
|
-
-- Poll for both tasks (qty=2)
|
|
15
|
-
select * from pgflow.poll_for_tasks('timeout_test', vt => 1, qty => 999);
|
|
16
|
-
|
|
17
|
-
-- Assert that vt_delay is set to opt_timeout + 2 for each step
|
|
18
|
-
select pgflow_tests.assert_retry_delay(
|
|
19
|
-
'timeout_test',
|
|
20
|
-
'step_30',
|
|
21
|
-
32, -- 30 + 2
|
|
22
|
-
'step_30 should have vt_delay set to opt_timeout (30) + 2 seconds'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
select pgflow_tests.assert_retry_delay(
|
|
26
|
-
'timeout_test',
|
|
27
|
-
'step_45',
|
|
28
|
-
47, -- 45 + 2
|
|
29
|
-
'step_45 should have vt_delay set to opt_timeout (45) + 2 seconds'
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
-- Assert that by default it will use flow opt_timeout + 2 if not overridden
|
|
33
|
-
select pgflow_tests.assert_retry_delay(
|
|
34
|
-
'timeout_test',
|
|
35
|
-
'step_with_flow_timeout',
|
|
36
|
-
62, -- 60 + 2
|
|
37
|
-
'step_with_flow_timeout should have vt_delay set to flow opt_timeout (60) + 2 seconds'
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
select * from finish();
|
|
41
|
-
rollback;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select * from plan(4);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run which will put a single task in the queue
|
|
7
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- TEST: Poll a single task
|
|
10
|
-
select is(
|
|
11
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
12
|
-
queue_name => 'sequential'::text,
|
|
13
|
-
vt => 1,
|
|
14
|
-
qty => 1,
|
|
15
|
-
max_poll_seconds => 1
|
|
16
|
-
)),
|
|
17
|
-
1::integer,
|
|
18
|
-
'First poll should get the available task'
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
-- TEST: Second poll before vt expires should not get the task
|
|
22
|
-
select is(
|
|
23
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
24
|
-
queue_name => 'sequential'::text,
|
|
25
|
-
vt => 1,
|
|
26
|
-
qty => 1,
|
|
27
|
-
max_poll_seconds => 1
|
|
28
|
-
)),
|
|
29
|
-
0::integer,
|
|
30
|
-
'Second poll before vt expires should not get the task'
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
-- Wait longer than the visibility timeout
|
|
34
|
-
select pg_sleep(2);
|
|
35
|
-
|
|
36
|
-
-- TEST: Second poll should get the task again because visibility timeout expired
|
|
37
|
-
select is(
|
|
38
|
-
(select count(*)::integer from pgflow.poll_for_tasks(
|
|
39
|
-
queue_name => 'sequential'::text,
|
|
40
|
-
vt => 1,
|
|
41
|
-
qty => 1,
|
|
42
|
-
max_poll_seconds => 1
|
|
43
|
-
)),
|
|
44
|
-
1::integer,
|
|
45
|
-
'Second poll should get the task again after visibility timeout expired'
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
-- Verify the task was re-polled (should be the same task)
|
|
49
|
-
select is(
|
|
50
|
-
(
|
|
51
|
-
select status from pgflow.step_tasks
|
|
52
|
-
where flow_slug = 'sequential' and step_slug = 'first'
|
|
53
|
-
),
|
|
54
|
-
'queued',
|
|
55
|
-
'The task should be queued'
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
select * from finish();
|
|
59
|
-
rollback;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
-- SETUP: Start a flow run
|
|
7
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
8
|
-
|
|
9
|
-
-- TEST: Run should be created
|
|
10
|
-
select results_eq(
|
|
11
|
-
$$ SELECT flow_slug, status, input from pgflow.runs $$,
|
|
12
|
-
$$ VALUES ('sequential', 'started', '"hello"'::jsonb) $$,
|
|
13
|
-
'Run should be created with appropriate status and input'
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
-- TEST: remaining_steps should be equal to number of steps
|
|
17
|
-
select is(
|
|
18
|
-
(select remaining_steps::int from pgflow.runs limit 1),
|
|
19
|
-
3::int,
|
|
20
|
-
'remaining_steps should be equal to number of steps'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
select finish();
|
|
24
|
-
rollback;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
select pgflow_tests.setup_flow('sequential_other');
|
|
6
|
-
|
|
7
|
-
-- SETUP: Start a flow run
|
|
8
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
9
|
-
|
|
10
|
-
-- TEST: All step states from flow should be created
|
|
11
|
-
select set_eq(
|
|
12
|
-
$$ SELECT step_slug
|
|
13
|
-
FROM pgflow.step_states WHERE flow_slug = 'sequential' $$,
|
|
14
|
-
array['first', 'second', 'last']::text [],
|
|
15
|
-
'All step states from flow should be created'
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
-- TEST: No steps from other flows should be created
|
|
19
|
-
select is_empty(
|
|
20
|
-
$$ SELECT * FROM pgflow.step_states WHERE flow_slug <> 'sequential' $$,
|
|
21
|
-
'No steps from other flows should be created'
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
select finish();
|
|
25
|
-
rollback;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(5);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('two_roots');
|
|
5
|
-
|
|
6
|
-
select pgflow.start_flow('two_roots', '"hello"'::jsonb);
|
|
7
|
-
|
|
8
|
-
-- TEST: A step_task record should be created only for the root step
|
|
9
|
-
select is(
|
|
10
|
-
(
|
|
11
|
-
select
|
|
12
|
-
array_agg(
|
|
13
|
-
step_slug
|
|
14
|
-
order by step_slug
|
|
15
|
-
)
|
|
16
|
-
from pgflow.step_tasks
|
|
17
|
-
where flow_slug = 'two_roots'
|
|
18
|
-
),
|
|
19
|
-
array['root_a', 'root_b']::text [],
|
|
20
|
-
'A step_task record should be created for each root step'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
-- TEST: Two messages should be in the queue, one per each root step
|
|
24
|
-
select is(
|
|
25
|
-
(select count(*)::int from pgmq.q_two_roots),
|
|
26
|
-
2::int,
|
|
27
|
-
'Two messages should be in the queue, one per each root step'
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
-- TEST; Messages have appropriate flow slugs
|
|
31
|
-
select is(
|
|
32
|
-
(select array_agg(message ->> 'flow_slug') from pgmq.q_two_roots),
|
|
33
|
-
array['two_roots', 'two_roots'],
|
|
34
|
-
'Messages have appropriate flow slugs'
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
-- TEST: Messages have appropriate step slugs
|
|
38
|
-
select is(
|
|
39
|
-
(select array_agg(message ->> 'step_slug') from pgmq.q_two_roots),
|
|
40
|
-
array['root_a', 'root_b']::text [],
|
|
41
|
-
'Messages have appropriate step slugs'
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
select is(
|
|
45
|
-
(select array_agg(message ->> 'run_id') from pgmq.q_two_roots),
|
|
46
|
-
(
|
|
47
|
-
select array_agg(run_id::text) from pgflow.step_tasks
|
|
48
|
-
where flow_slug = 'two_roots'
|
|
49
|
-
),
|
|
50
|
-
'Messages have appropriate run_ids'
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
select finish();
|
|
54
|
-
rollback;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
select pgflow_tests.setup_flow('two_roots');
|
|
6
|
-
|
|
7
|
-
-- TEST: start_flow() returns started step states
|
|
8
|
-
select results_eq(
|
|
9
|
-
$$ SELECT flow_slug, status, input
|
|
10
|
-
FROM pgflow.start_flow('sequential', '"hello"'::jsonb) $$,
|
|
11
|
-
$$ VALUES ('sequential', 'started', '"hello"'::jsonb) $$,
|
|
12
|
-
'start_flow() should return a run'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
-- TEST: start_flow() returns started step states
|
|
16
|
-
select results_eq(
|
|
17
|
-
$$ SELECT flow_slug, status, input
|
|
18
|
-
FROM pgflow.start_flow('sequential', '"world"'::jsonb) $$,
|
|
19
|
-
$$ VALUES ('sequential', 'started', '"world"'::jsonb) $$,
|
|
20
|
-
'start_flow() should return a single run even for flow that have two root steps'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
select finish();
|
|
24
|
-
rollback;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(2);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
select pgflow_tests.setup_flow('sequential');
|
|
5
|
-
|
|
6
|
-
select pgflow.start_flow('sequential', '"hello"'::jsonb);
|
|
7
|
-
|
|
8
|
-
-- TEST: A step_task record should be created only for the root step
|
|
9
|
-
select is(
|
|
10
|
-
(
|
|
11
|
-
select
|
|
12
|
-
array_agg(
|
|
13
|
-
step_slug
|
|
14
|
-
order by step_slug
|
|
15
|
-
)
|
|
16
|
-
from pgflow.step_tasks
|
|
17
|
-
where flow_slug = 'sequential'
|
|
18
|
-
),
|
|
19
|
-
array['first']::text [],
|
|
20
|
-
'A step_task record should be created only for the root step'
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
-- TEST: The message in the queue should contain the correct step info
|
|
24
|
-
select is(
|
|
25
|
-
(
|
|
26
|
-
select q.message
|
|
27
|
-
from pgflow.step_tasks as st
|
|
28
|
-
inner join pgmq.q_sequential as q
|
|
29
|
-
on st.message_id = q.msg_id
|
|
30
|
-
where
|
|
31
|
-
st.flow_slug = 'sequential'
|
|
32
|
-
and st.step_slug = 'first'
|
|
33
|
-
),
|
|
34
|
-
jsonb_build_object(
|
|
35
|
-
'flow_slug', 'sequential',
|
|
36
|
-
'run_id', (
|
|
37
|
-
select run_id
|
|
38
|
-
from pgflow.step_tasks
|
|
39
|
-
where
|
|
40
|
-
flow_slug = 'sequential'
|
|
41
|
-
and step_slug = 'first'
|
|
42
|
-
),
|
|
43
|
-
'step_slug', 'first',
|
|
44
|
-
'task_index', 0
|
|
45
|
-
),
|
|
46
|
-
'The message in the queue should contain the correct step info'
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
select finish();
|
|
50
|
-
rollback;
|