@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.
Files changed (110) hide show
  1. package/{CHANGELOG.md → dist/CHANGELOG.md} +6 -0
  2. package/package.json +8 -5
  3. package/__tests__/mocks/index.ts +0 -1
  4. package/__tests__/mocks/postgres.ts +0 -37
  5. package/__tests__/types/PgflowSqlClient.test-d.ts +0 -59
  6. package/docs/options_for_flow_and_steps.md +0 -75
  7. package/docs/pgflow-blob-reference-system.md +0 -179
  8. package/eslint.config.cjs +0 -22
  9. package/example-flow.mermaid +0 -5
  10. package/example-flow.svg +0 -1
  11. package/flow-lifecycle.mermaid +0 -83
  12. package/flow-lifecycle.svg +0 -1
  13. package/out-tsc/vitest/__tests__/mocks/index.d.ts +0 -2
  14. package/out-tsc/vitest/__tests__/mocks/index.d.ts.map +0 -1
  15. package/out-tsc/vitest/__tests__/mocks/postgres.d.ts +0 -15
  16. package/out-tsc/vitest/__tests__/mocks/postgres.d.ts.map +0 -1
  17. package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts +0 -2
  18. package/out-tsc/vitest/__tests__/types/PgflowSqlClient.test-d.d.ts.map +0 -1
  19. package/out-tsc/vitest/tsconfig.spec.tsbuildinfo +0 -1
  20. package/out-tsc/vitest/vite.config.d.ts +0 -3
  21. package/out-tsc/vitest/vite.config.d.ts.map +0 -1
  22. package/pkgs/core/dist/index.js +0 -54
  23. package/pkgs/core/dist/pkgs/core/LICENSE.md +0 -660
  24. package/pkgs/core/dist/pkgs/core/README.md +0 -373
  25. package/pkgs/dsl/dist/index.js +0 -123
  26. package/pkgs/dsl/dist/pkgs/dsl/README.md +0 -11
  27. package/pkgs/edge-worker/dist/index.js +0 -953
  28. package/pkgs/edge-worker/dist/index.js.map +0 -7
  29. package/pkgs/edge-worker/dist/pkgs/edge-worker/LICENSE.md +0 -660
  30. package/pkgs/edge-worker/dist/pkgs/edge-worker/README.md +0 -46
  31. package/pkgs/example-flows/dist/index.js +0 -152
  32. package/pkgs/example-flows/dist/pkgs/example-flows/README.md +0 -11
  33. package/project.json +0 -125
  34. package/prompts/architect.md +0 -87
  35. package/prompts/condition.md +0 -33
  36. package/prompts/declarative_sql.md +0 -15
  37. package/prompts/deps_in_payloads.md +0 -20
  38. package/prompts/dsl-multi-arg.ts +0 -48
  39. package/prompts/dsl-options.md +0 -39
  40. package/prompts/dsl-single-arg.ts +0 -51
  41. package/prompts/dsl-two-arg.ts +0 -61
  42. package/prompts/dsl.md +0 -119
  43. package/prompts/fanout_steps.md +0 -1
  44. package/prompts/json_schemas.md +0 -36
  45. package/prompts/one_shot.md +0 -286
  46. package/prompts/pgtap.md +0 -229
  47. package/prompts/sdk.md +0 -59
  48. package/prompts/step_types.md +0 -62
  49. package/prompts/versioning.md +0 -16
  50. package/queries/fail_permanently.sql +0 -17
  51. package/queries/fail_task.sql +0 -21
  52. package/queries/sequential.sql +0 -47
  53. package/queries/two_roots_left_right.sql +0 -59
  54. package/schema.svg +0 -1
  55. package/scripts/colorize-pgtap-output.awk +0 -72
  56. package/scripts/run-test-with-colors +0 -5
  57. package/scripts/watch-test +0 -7
  58. package/src/PgflowSqlClient.ts +0 -85
  59. package/src/database-types.ts +0 -759
  60. package/src/index.ts +0 -3
  61. package/src/types.ts +0 -103
  62. package/supabase/config.toml +0 -32
  63. package/supabase/seed.sql +0 -202
  64. package/supabase/tests/add_step/basic_step_addition.test.sql +0 -29
  65. package/supabase/tests/add_step/circular_dependency.test.sql +0 -21
  66. package/supabase/tests/add_step/flow_isolation.test.sql +0 -26
  67. package/supabase/tests/add_step/idempotent_step_addition.test.sql +0 -20
  68. package/supabase/tests/add_step/invalid_step_slug.test.sql +0 -16
  69. package/supabase/tests/add_step/nonexistent_dependency.test.sql +0 -16
  70. package/supabase/tests/add_step/nonexistent_flow.test.sql +0 -13
  71. package/supabase/tests/add_step/options.test.sql +0 -66
  72. package/supabase/tests/add_step/step_with_dependency.test.sql +0 -36
  73. package/supabase/tests/add_step/step_with_multiple_dependencies.test.sql +0 -46
  74. package/supabase/tests/complete_task/archives_message.test.sql +0 -67
  75. package/supabase/tests/complete_task/completes_run_if_no_more_remaining_steps.test.sql +0 -62
  76. package/supabase/tests/complete_task/completes_task_and_updates_dependents.test.sql +0 -64
  77. package/supabase/tests/complete_task/decrements_remaining_steps_if_completing_step.test.sql +0 -62
  78. package/supabase/tests/complete_task/saves_output_when_completing_run.test.sql +0 -57
  79. package/supabase/tests/create_flow/flow_creation.test.sql +0 -27
  80. package/supabase/tests/create_flow/idempotency_and_duplicates.test.sql +0 -26
  81. package/supabase/tests/create_flow/invalid_slug.test.sql +0 -13
  82. package/supabase/tests/create_flow/options.test.sql +0 -57
  83. package/supabase/tests/fail_task/exponential_backoff.test.sql +0 -70
  84. package/supabase/tests/fail_task/mark_as_failed_if_no_retries_available.test.sql +0 -49
  85. package/supabase/tests/fail_task/respects_flow_retry_settings.test.sql +0 -48
  86. package/supabase/tests/fail_task/respects_step_retry_settings.test.sql +0 -48
  87. package/supabase/tests/fail_task/retry_task_if_retries_available.test.sql +0 -39
  88. package/supabase/tests/is_valid_slug.test.sql +0 -72
  89. package/supabase/tests/poll_for_tasks/builds_proper_input_from_deps_outputs.test.sql +0 -35
  90. package/supabase/tests/poll_for_tasks/hides_messages.test.sql +0 -35
  91. package/supabase/tests/poll_for_tasks/increments_attempts_count.test.sql +0 -35
  92. package/supabase/tests/poll_for_tasks/multiple_task_processing.test.sql +0 -24
  93. package/supabase/tests/poll_for_tasks/polls_only_queued_tasks.test.sql +0 -35
  94. package/supabase/tests/poll_for_tasks/reads_messages.test.sql +0 -38
  95. package/supabase/tests/poll_for_tasks/returns_no_tasks_if_no_step_task_for_message.test.sql +0 -34
  96. package/supabase/tests/poll_for_tasks/returns_no_tasks_if_queue_is_empty.test.sql +0 -19
  97. package/supabase/tests/poll_for_tasks/returns_no_tasks_when_qty_set_to_0.test.sql +0 -22
  98. package/supabase/tests/poll_for_tasks/sets_vt_delay_based_on_opt_timeout.test.sql +0 -41
  99. package/supabase/tests/poll_for_tasks/tasks_reapppear_if_not_processed_in_time.test.sql +0 -59
  100. package/supabase/tests/start_flow/creates_run.test.sql +0 -24
  101. package/supabase/tests/start_flow/creates_step_states_for_all_steps.test.sql +0 -25
  102. package/supabase/tests/start_flow/creates_step_tasks_only_for_root_steps.test.sql +0 -54
  103. package/supabase/tests/start_flow/returns_run.test.sql +0 -24
  104. package/supabase/tests/start_flow/sends_messages_on_the_queue.test.sql +0 -50
  105. package/supabase/tests/start_flow/starts_only_root_steps.test.sql +0 -21
  106. package/supabase/tests/step_dsl_is_idempotent.test.sql +0 -34
  107. package/tsconfig.json +0 -16
  108. package/tsconfig.lib.json +0 -26
  109. package/tsconfig.spec.json +0 -35
  110. 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;