@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
package/src/index.ts
DELETED
package/src/types.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ExtractFlowSteps,
|
|
3
|
-
StepInput,
|
|
4
|
-
Simplify,
|
|
5
|
-
AnyFlow,
|
|
6
|
-
} from '@pgflow/dsl';
|
|
7
|
-
import type { Database } from './database-types.ts';
|
|
8
|
-
|
|
9
|
-
export type Json =
|
|
10
|
-
| string
|
|
11
|
-
| number
|
|
12
|
-
| boolean
|
|
13
|
-
| null
|
|
14
|
-
| { [key: string]: Json | undefined }
|
|
15
|
-
| Json[];
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Record representing a task from pgflow.poll_for_tasks
|
|
19
|
-
*
|
|
20
|
-
* Same as pgflow.step_task_record type, but with not-null fields and type argument for payload.
|
|
21
|
-
* The input type is automatically inferred based on the step_slug using a discriminated union.
|
|
22
|
-
* This ensures that each step only receives inputs from its declared dependencies and the flow's run input.
|
|
23
|
-
*/
|
|
24
|
-
export type StepTaskRecord<TFlow extends AnyFlow> = {
|
|
25
|
-
[StepSlug in Extract<keyof ExtractFlowSteps<TFlow>, string>]: {
|
|
26
|
-
flow_slug: string;
|
|
27
|
-
run_id: string;
|
|
28
|
-
step_slug: StepSlug;
|
|
29
|
-
input: Simplify<StepInput<TFlow, StepSlug>>;
|
|
30
|
-
msg_id: number;
|
|
31
|
-
};
|
|
32
|
-
}[Extract<keyof ExtractFlowSteps<TFlow>, string>];
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Composite key that is enough to find a particular step task
|
|
36
|
-
* Contains only the minimum fields needed to identify a task
|
|
37
|
-
*/
|
|
38
|
-
export type StepTaskKey = Pick<StepTaskRecord<any>, 'run_id' | 'step_slug'>;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Interface for interacting with pgflow database functions
|
|
42
|
-
*/
|
|
43
|
-
export interface IPgflowClient<TFlow extends AnyFlow = AnyFlow> {
|
|
44
|
-
/**
|
|
45
|
-
* Fetches tasks from pgflow
|
|
46
|
-
* @param queueName - Name
|
|
47
|
-
* @param batchSize - Number of tasks to fetch
|
|
48
|
-
* @param visibilityTimeout - Visibility timeout for tasks
|
|
49
|
-
* @param maxPollSeconds - Maximum time to poll for tasks
|
|
50
|
-
* @param pollIntervalMs - Poll interval in milliseconds
|
|
51
|
-
*/
|
|
52
|
-
pollForTasks(
|
|
53
|
-
queueName: string,
|
|
54
|
-
batchSize?: number,
|
|
55
|
-
visibilityTimeout?: number,
|
|
56
|
-
maxPollSeconds?: number,
|
|
57
|
-
pollIntervalMs?: number
|
|
58
|
-
): Promise<StepTaskRecord<TFlow>[]>;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Marks a task as completed
|
|
62
|
-
* @param stepTask - Step task key containing run_id and step_slug
|
|
63
|
-
* @param output - Output payload for the task
|
|
64
|
-
*/
|
|
65
|
-
completeTask(stepTask: StepTaskKey, output?: Json): Promise<void>;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Marks a task as failed
|
|
69
|
-
* @param stepTask - Step task key containing run_id and step_slug
|
|
70
|
-
* @param error - Error to fail task with
|
|
71
|
-
*/
|
|
72
|
-
failTask(stepTask: StepTaskKey, error: unknown): Promise<void>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Record representing a flow from pgflow.flows
|
|
77
|
-
*/
|
|
78
|
-
export type FlowRow = Database['pgflow']['Tables']['flows']['Row'];
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Record representing a step from pgflow.steps
|
|
82
|
-
*/
|
|
83
|
-
export type StepRow = Database['pgflow']['Tables']['steps']['Row'];
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Record representing a step from pgflow.deps
|
|
87
|
-
*/
|
|
88
|
-
export type DepRow = Database['pgflow']['Tables']['deps']['Row'];
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Record representing a step from pgflow.queues
|
|
92
|
-
*/
|
|
93
|
-
export type RunRow = Database['pgflow']['Tables']['runs']['Row'];
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Record representing a step from pgflow.step_states
|
|
97
|
-
*/
|
|
98
|
-
export type StepStateRow = Database['pgflow']['Tables']['step_states']['Row'];
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Record representing a step from pgflow.step_tasks
|
|
102
|
-
*/
|
|
103
|
-
export type StepTaskRow = Database['pgflow']['Tables']['step_tasks']['Row'];
|
package/supabase/config.toml
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
project_id = "core"
|
|
2
|
-
|
|
3
|
-
[db]
|
|
4
|
-
port = 50422
|
|
5
|
-
shadow_port = 50420
|
|
6
|
-
major_version = 15
|
|
7
|
-
|
|
8
|
-
# disable unused features
|
|
9
|
-
[db.seed]
|
|
10
|
-
enabled = true
|
|
11
|
-
|
|
12
|
-
[api]
|
|
13
|
-
port = 50421 # Add custom port for Kong
|
|
14
|
-
enabled = false # Keep disabled as per your config
|
|
15
|
-
[db.pooler]
|
|
16
|
-
enabled = false
|
|
17
|
-
[edge_runtime]
|
|
18
|
-
enabled = false
|
|
19
|
-
[realtime]
|
|
20
|
-
enabled = false
|
|
21
|
-
[studio]
|
|
22
|
-
enabled = false
|
|
23
|
-
[inbucket]
|
|
24
|
-
enabled = false
|
|
25
|
-
[analytics]
|
|
26
|
-
enabled = false
|
|
27
|
-
[storage]
|
|
28
|
-
enabled = false
|
|
29
|
-
[auth]
|
|
30
|
-
enabled = false
|
|
31
|
-
|
|
32
|
-
|
package/supabase/seed.sql
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
create schema if not exists pgflow_tests;
|
|
2
|
-
|
|
3
|
-
--------------------------------------------------------------------------------
|
|
4
|
-
--------- reset_db - clears all tables and drops all queues --------------------
|
|
5
|
-
--------------------------------------------------------------------------------
|
|
6
|
-
create or replace function pgflow_tests.reset_db() returns void as $$
|
|
7
|
-
DELETE FROM pgflow.step_tasks;
|
|
8
|
-
DELETE FROM pgflow.step_states;
|
|
9
|
-
DELETE FROM pgflow.runs;
|
|
10
|
-
DELETE FROM pgflow.deps;
|
|
11
|
-
DELETE FROM pgflow.steps;
|
|
12
|
-
DELETE FROM pgflow.flows;
|
|
13
|
-
|
|
14
|
-
SELECT pgmq.drop_queue(queue_name) FROM pgmq.list_queues();
|
|
15
|
-
$$ language sql;
|
|
16
|
-
|
|
17
|
-
--------------------------------------------------------------------------------
|
|
18
|
-
--------- setup_flow - creates a predefined flow and adds steps to it ----------
|
|
19
|
-
--------------------------------------------------------------------------------
|
|
20
|
-
create or replace function pgflow_tests.setup_flow(
|
|
21
|
-
flow_slug text
|
|
22
|
-
) returns void as $$
|
|
23
|
-
begin
|
|
24
|
-
|
|
25
|
-
if flow_slug = 'sequential' then
|
|
26
|
-
PERFORM pgflow.create_flow('sequential', timeout => 1);
|
|
27
|
-
PERFORM pgflow.add_step('sequential', 'first');
|
|
28
|
-
PERFORM pgflow.add_step('sequential', 'second', ARRAY['first']);
|
|
29
|
-
PERFORM pgflow.add_step('sequential', 'last', ARRAY['second']);
|
|
30
|
-
elsif flow_slug = 'sequential_other' then
|
|
31
|
-
PERFORM pgflow.create_flow('other', timeout => 1);
|
|
32
|
-
PERFORM pgflow.add_step('other', 'first');
|
|
33
|
-
PERFORM pgflow.add_step('other', 'second', ARRAY['first']);
|
|
34
|
-
PERFORM pgflow.add_step('other', 'last', ARRAY['second']);
|
|
35
|
-
elsif flow_slug = 'two_roots' then
|
|
36
|
-
PERFORM pgflow.create_flow('two_roots', timeout => 1);
|
|
37
|
-
PERFORM pgflow.add_step('two_roots', 'root_a');
|
|
38
|
-
PERFORM pgflow.add_step('two_roots', 'root_b');
|
|
39
|
-
PERFORM pgflow.add_step('two_roots', 'last', ARRAY['root_a', 'root_b']);
|
|
40
|
-
elsif flow_slug = 'two_roots_left_right' then
|
|
41
|
-
PERFORM pgflow.create_flow('two_roots_left_right', timeout => 1);
|
|
42
|
-
PERFORM pgflow.add_step('two_roots_left_right', 'connected_root');
|
|
43
|
-
PERFORM pgflow.add_step('two_roots_left_right', 'disconnected_root');
|
|
44
|
-
PERFORM pgflow.add_step('two_roots_left_right', 'left', ARRAY['connected_root']);
|
|
45
|
-
PERFORM pgflow.add_step('two_roots_left_right', 'right', ARRAY['connected_root']);
|
|
46
|
-
else
|
|
47
|
-
RAISE EXCEPTION 'Unknown test flow: %', flow_slug;
|
|
48
|
-
end if;
|
|
49
|
-
|
|
50
|
-
end;
|
|
51
|
-
$$ language plpgsql;
|
|
52
|
-
|
|
53
|
-
--------------------------------------------------------------------------------
|
|
54
|
-
------- poll_and_fail - polls for a task and fails it immediately --------------
|
|
55
|
-
--------------------------------------------------------------------------------
|
|
56
|
-
create or replace function pgflow_tests.poll_and_fail(
|
|
57
|
-
flow_slug text,
|
|
58
|
-
vt integer default 1,
|
|
59
|
-
qty integer default 1
|
|
60
|
-
) returns setof pgflow.step_tasks as $$
|
|
61
|
-
-- Poll for a task and complete it in one step
|
|
62
|
-
WITH task AS (
|
|
63
|
-
SELECT * FROM pgflow.poll_for_tasks(flow_slug, vt, qty) LIMIT 1
|
|
64
|
-
)
|
|
65
|
-
SELECT pgflow.fail_task(
|
|
66
|
-
(SELECT run_id FROM task),
|
|
67
|
-
(SELECT step_slug FROM task),
|
|
68
|
-
0,
|
|
69
|
-
concat(task.step_slug, ' FAILED')
|
|
70
|
-
)
|
|
71
|
-
FROM task;
|
|
72
|
-
$$ language sql;
|
|
73
|
-
|
|
74
|
-
--------------------------------------------------------------------------------
|
|
75
|
-
------- poll_and_complete - polls for a task and completes it immediately ------
|
|
76
|
-
--------------------------------------------------------------------------------
|
|
77
|
-
create or replace function pgflow_tests.poll_and_complete(
|
|
78
|
-
flow_slug text,
|
|
79
|
-
vt integer default 1,
|
|
80
|
-
qty integer default 1
|
|
81
|
-
) returns setof pgflow.step_tasks as $$
|
|
82
|
-
-- Poll for a task and complete it in one step
|
|
83
|
-
WITH task AS (
|
|
84
|
-
SELECT * FROM pgflow.poll_for_tasks(flow_slug, vt, qty) LIMIT 1
|
|
85
|
-
)
|
|
86
|
-
SELECT pgflow.complete_task(
|
|
87
|
-
(SELECT run_id FROM task),
|
|
88
|
-
(SELECT step_slug FROM task),
|
|
89
|
-
0,
|
|
90
|
-
jsonb_build_object('input', task.input)
|
|
91
|
-
)
|
|
92
|
-
FROM task;
|
|
93
|
-
$$ language sql;
|
|
94
|
-
|
|
95
|
-
--------------------------------------------------------------------------------
|
|
96
|
-
------- message_timing - returns messages with added vt_seconds int ------------
|
|
97
|
-
--------------------------------------------------------------------------------
|
|
98
|
-
create or replace function pgflow_tests.message_timing(step_slug text, queue_name text)
|
|
99
|
-
returns table (
|
|
100
|
-
msg_id bigint,
|
|
101
|
-
read_ct int,
|
|
102
|
-
enqueued_at timestamptz,
|
|
103
|
-
vt timestamptz,
|
|
104
|
-
message jsonb,
|
|
105
|
-
vt_seconds int
|
|
106
|
-
)
|
|
107
|
-
language plpgsql
|
|
108
|
-
as $$
|
|
109
|
-
DECLARE
|
|
110
|
-
qtable TEXT;
|
|
111
|
-
query TEXT;
|
|
112
|
-
BEGIN
|
|
113
|
-
qtable := pgmq.format_table_name(queue_name, 'q');
|
|
114
|
-
|
|
115
|
-
query := format('
|
|
116
|
-
SELECT
|
|
117
|
-
q.msg_id,
|
|
118
|
-
q.read_ct,
|
|
119
|
-
q.enqueued_at,
|
|
120
|
-
q.vt,
|
|
121
|
-
q.message,
|
|
122
|
-
extract(epoch from (q.vt - q.enqueued_at))::int as vt_seconds
|
|
123
|
-
FROM pgmq.%s q
|
|
124
|
-
JOIN pgflow.step_tasks st ON st.message_id = q.msg_id
|
|
125
|
-
WHERE st.step_slug = $1', qtable);
|
|
126
|
-
|
|
127
|
-
RETURN QUERY EXECUTE query USING step_slug;
|
|
128
|
-
END;
|
|
129
|
-
$$;
|
|
130
|
-
|
|
131
|
-
--------------------------------------------------------------------------------
|
|
132
|
-
------- reset_message_visibility -----------------------------------------------
|
|
133
|
-
--------------------------------------------------------------------------------
|
|
134
|
-
--
|
|
135
|
-
-- Makes all hidden messages in a queue immediately visible by setting their
|
|
136
|
-
-- visibility time (vt) to the current timestamp.
|
|
137
|
-
--
|
|
138
|
-
-- This is a test utility that allows testing retry logic without waiting for
|
|
139
|
-
-- actual delays to expire. It directly modifies the pgmq queue table.
|
|
140
|
-
--
|
|
141
|
-
-- @param queue_name The name of the queue to modify
|
|
142
|
-
-- @return The number of messages that were made visible
|
|
143
|
-
--
|
|
144
|
-
create or replace function pgflow_tests.reset_message_visibility(
|
|
145
|
-
queue_name text
|
|
146
|
-
) returns integer as $$
|
|
147
|
-
DECLARE
|
|
148
|
-
qtable TEXT;
|
|
149
|
-
query TEXT;
|
|
150
|
-
updated_count INTEGER;
|
|
151
|
-
BEGIN
|
|
152
|
-
-- Get the formatted table name for the queue
|
|
153
|
-
qtable := pgmq.format_table_name(queue_name, 'q');
|
|
154
|
-
|
|
155
|
-
-- Construct and execute the query to update all messages' visibility time
|
|
156
|
-
query := format('
|
|
157
|
-
UPDATE pgmq.%s
|
|
158
|
-
SET vt = clock_timestamp()
|
|
159
|
-
WHERE vt > clock_timestamp()
|
|
160
|
-
RETURNING 1', qtable);
|
|
161
|
-
|
|
162
|
-
-- Execute the query and count the number of updated rows
|
|
163
|
-
EXECUTE query INTO updated_count;
|
|
164
|
-
|
|
165
|
-
-- Return the number of messages that were made visible
|
|
166
|
-
RETURN COALESCE(updated_count, 0);
|
|
167
|
-
END;
|
|
168
|
-
$$ language plpgsql;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
--------------------------------------------------------------------------------
|
|
172
|
-
------- assert_retry_delay -----------------------------------------------------
|
|
173
|
-
--------------------------------------------------------------------------------
|
|
174
|
-
--
|
|
175
|
-
-- Asserts that the calculated retry delay matches the expected value.
|
|
176
|
-
--
|
|
177
|
-
-- @param step_slug The slug of the step to check
|
|
178
|
-
-- @param queue_name The name of the queue to check
|
|
179
|
-
-- @param expected_delay The expected delay value
|
|
180
|
-
-- @param description A description of the test case
|
|
181
|
-
-- @return TEXT result from the is() function
|
|
182
|
-
--
|
|
183
|
-
create or replace function pgflow_tests.assert_retry_delay(
|
|
184
|
-
queue_name text,
|
|
185
|
-
step_slug text,
|
|
186
|
-
expected_delay integer,
|
|
187
|
-
description text
|
|
188
|
-
) returns text as $$
|
|
189
|
-
DECLARE
|
|
190
|
-
actual_delay INTEGER;
|
|
191
|
-
BEGIN
|
|
192
|
-
SELECT vt_seconds INTO actual_delay
|
|
193
|
-
FROM pgflow_tests.message_timing(step_slug, queue_name)
|
|
194
|
-
LIMIT 1;
|
|
195
|
-
|
|
196
|
-
RETURN is(
|
|
197
|
-
actual_delay,
|
|
198
|
-
expected_delay,
|
|
199
|
-
description
|
|
200
|
-
);
|
|
201
|
-
END;
|
|
202
|
-
$$ language plpgsql;
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
|
|
8
|
-
-- Test
|
|
9
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
10
|
-
select results_eq(
|
|
11
|
-
$$ SELECT step_slug FROM pgflow.steps WHERE flow_slug = 'test_flow' $$,
|
|
12
|
-
array['first_step']::text [],
|
|
13
|
-
'Step should be added to the steps table'
|
|
14
|
-
);
|
|
15
|
-
select is_empty(
|
|
16
|
-
$$ SELECT * FROM pgflow.deps WHERE flow_slug = 'test_flow' $$,
|
|
17
|
-
'No dependencies should be added for step with no dependencies'
|
|
18
|
-
);
|
|
19
|
-
select is(
|
|
20
|
-
(
|
|
21
|
-
select deps_count::int from pgflow.steps
|
|
22
|
-
where flow_slug = 'test_flow'
|
|
23
|
-
),
|
|
24
|
-
0::int,
|
|
25
|
-
'deps_count should be 0 because there are no dependencies'
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
select * from finish();
|
|
29
|
-
rollback;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
8
|
-
select pgflow.add_step('test_flow', 'second_step', array['first_step']);
|
|
9
|
-
select pgflow.add_step('test_flow', 'third_step', array['second_step']);
|
|
10
|
-
select
|
|
11
|
-
pgflow.add_step('test_flow', 'fourth_step', array['second_step', 'third_step']);
|
|
12
|
-
|
|
13
|
-
-- Test
|
|
14
|
-
select throws_ok(
|
|
15
|
-
$$ SELECT pgflow.add_step('test_flow', 'circular_step', ARRAY['fourth_step', 'circular_step']) $$,
|
|
16
|
-
'new row for relation "deps" violates check constraint "deps_check"',
|
|
17
|
-
'Should not allow self-depending steps'
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
select * from finish();
|
|
21
|
-
rollback;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
8
|
-
select pgflow.create_flow('another_flow');
|
|
9
|
-
|
|
10
|
-
-- Test
|
|
11
|
-
select pgflow.add_step('another_flow', 'first_step');
|
|
12
|
-
select pgflow.add_step('another_flow', 'another_step', array['first_step']);
|
|
13
|
-
select set_eq(
|
|
14
|
-
$$
|
|
15
|
-
SELECT flow_slug, step_slug
|
|
16
|
-
FROM pgflow.steps WHERE flow_slug = 'another_flow'
|
|
17
|
-
$$,
|
|
18
|
-
$$ VALUES
|
|
19
|
-
('another_flow', 'another_step'),
|
|
20
|
-
('another_flow', 'first_step')
|
|
21
|
-
$$,
|
|
22
|
-
'Steps in second flow should be isolated from first flow'
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
select * from finish();
|
|
26
|
-
rollback;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
8
|
-
|
|
9
|
-
-- Test
|
|
10
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
11
|
-
select results_eq(
|
|
12
|
-
$$
|
|
13
|
-
SELECT count(*)::int FROM pgflow.steps WHERE flow_slug = 'test_flow' AND step_slug = 'first_step'
|
|
14
|
-
$$,
|
|
15
|
-
array[1]::int [],
|
|
16
|
-
'Calling add_step again for same step does not create a duplicate'
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
select * from finish();
|
|
20
|
-
rollback;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
|
|
8
|
-
-- Test
|
|
9
|
-
select throws_ok(
|
|
10
|
-
$$ SELECT pgflow.add_step('test_flow', '1invalid-slug') $$,
|
|
11
|
-
'new row for relation "steps" violates check constraint "steps_step_slug_check"',
|
|
12
|
-
'Should detect and prevent invalid step slug'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
select * from finish();
|
|
16
|
-
rollback;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
|
|
8
|
-
-- Test
|
|
9
|
-
select throws_ok(
|
|
10
|
-
$$ SELECT pgflow.add_step('test_flow', 'invalid_dep_step', ARRAY['nonexistent_step']) $$,
|
|
11
|
-
'insert or update on table "deps" violates foreign key constraint "deps_flow_slug_dep_slug_fkey"',
|
|
12
|
-
'Should detect and prevent dependency on non-existent step'
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
select * from finish();
|
|
16
|
-
rollback;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(1);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Test
|
|
6
|
-
select throws_ok(
|
|
7
|
-
$$ SELECT pgflow.add_step('nonexistent_flow', 'some_step') $$,
|
|
8
|
-
'insert or update on table "steps" violates foreign key constraint "steps_flow_slug_fkey"',
|
|
9
|
-
'Should not allow adding step to non-existent flow'
|
|
10
|
-
);
|
|
11
|
-
|
|
12
|
-
select * from finish();
|
|
13
|
-
rollback;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(6);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- SETUP: Create flow with steps
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'default_options');
|
|
8
|
-
select pgflow.add_step('test_flow', 'overriden_max_attempts', max_attempts => 20);
|
|
9
|
-
select pgflow.add_step('test_flow', 'overriden_base_delay', base_delay => 30);
|
|
10
|
-
select pgflow.add_step('test_flow', 'overriden_timeout', timeout => 30);
|
|
11
|
-
|
|
12
|
-
-- TEST: opt_max_attempts, opt_base_delay and opt_timeout are NULL by default
|
|
13
|
-
select results_eq(
|
|
14
|
-
$$ SELECT opt_max_attempts is null, opt_base_delay is null, opt_timeout is null
|
|
15
|
-
FROM pgflow.steps
|
|
16
|
-
WHERE step_slug = 'default_options' $$,
|
|
17
|
-
$$ VALUES (true, true, true) $$,
|
|
18
|
-
'opt_max_attempts, opt_base_delay and opt_timeout are NULL by default'
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
-- TEST: opt_max_attempts can be set
|
|
22
|
-
select is(
|
|
23
|
-
(select opt_max_attempts from pgflow.steps where step_slug = 'overriden_max_attempts'),
|
|
24
|
-
20,
|
|
25
|
-
'opt_max_attempts can be set'
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
-- TEST: opt_base_delay can be set
|
|
29
|
-
select is(
|
|
30
|
-
(select opt_base_delay from pgflow.steps where step_slug = 'overriden_base_delay'),
|
|
31
|
-
30,
|
|
32
|
-
'opt_base_delay can be set'
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
-- TEST: opt_timeout can be set
|
|
36
|
-
select is(
|
|
37
|
-
(select opt_timeout from pgflow.steps where step_slug = 'overriden_timeout'),
|
|
38
|
-
30,
|
|
39
|
-
'opt_timeout can be set'
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
-- SETUP: Add same step again to make sure it doesnt get updated
|
|
43
|
-
select pgflow.add_step('test_flow', 'added_twice', max_attempts => 10, base_delay => 15, timeout => 90);
|
|
44
|
-
select pgflow.add_step('test_flow', 'added_twice', max_attempts => 20, base_delay => 30, timeout => 30);
|
|
45
|
-
|
|
46
|
-
--TEST: Should not update opt_max_attempts, opt_base_delay and opt_timeout
|
|
47
|
-
select results_eq(
|
|
48
|
-
$$ SELECT opt_max_attempts, opt_base_delay, opt_timeout FROM pgflow.steps WHERE step_slug = 'added_twice' $$,
|
|
49
|
-
$$ VALUES (10, 15, 90) $$,
|
|
50
|
-
'Should not update opt_max_attempts, opt_base_delay and opt_timeout'
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
-- SETUP: Add step defined with default values again to make sure it doesnt get updated
|
|
54
|
-
select pgflow.add_step('test_flow', 'default_options', max_attempts => 0, base_delay => 15, timeout => 90);
|
|
55
|
-
|
|
56
|
-
-- TEST: Should not update opt_max_attempts, opt_base_delay and opt_timeout
|
|
57
|
-
select results_eq(
|
|
58
|
-
$$ SELECT opt_max_attempts is null, opt_base_delay is null, opt_timeout is null
|
|
59
|
-
FROM pgflow.steps
|
|
60
|
-
WHERE step_slug = 'default_options' $$,
|
|
61
|
-
$$ VALUES (true, true, true) $$,
|
|
62
|
-
'Should not update opt_max_attempts, opt_base_delay and opt_timeout for step with default values'
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
select * from finish();
|
|
66
|
-
rollback;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
8
|
-
|
|
9
|
-
-- Test
|
|
10
|
-
select pgflow.add_step('test_flow', 'second_step', array['first_step']);
|
|
11
|
-
select results_eq(
|
|
12
|
-
$$ SELECT step_slug FROM pgflow.steps WHERE flow_slug = 'test_flow' ORDER BY step_slug $$,
|
|
13
|
-
array['first_step', 'second_step']::text [],
|
|
14
|
-
'Second step should be added to the steps table'
|
|
15
|
-
);
|
|
16
|
-
select is(
|
|
17
|
-
(
|
|
18
|
-
select deps_count::int
|
|
19
|
-
from pgflow.steps
|
|
20
|
-
where flow_slug = 'test_flow' and step_slug = 'second_step'
|
|
21
|
-
),
|
|
22
|
-
1::int,
|
|
23
|
-
'deps_count should be 1 because "second_step" has one dependency'
|
|
24
|
-
);
|
|
25
|
-
select results_eq(
|
|
26
|
-
$$
|
|
27
|
-
SELECT dep_slug, step_slug
|
|
28
|
-
FROM pgflow.deps WHERE flow_slug = 'test_flow'
|
|
29
|
-
ORDER BY dep_slug, step_slug
|
|
30
|
-
$$,
|
|
31
|
-
$$ VALUES ('first_step', 'second_step') $$,
|
|
32
|
-
'Dependency should be recorded in deps table'
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
select * from finish();
|
|
36
|
-
rollback;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
begin;
|
|
2
|
-
select plan(3);
|
|
3
|
-
select pgflow_tests.reset_db();
|
|
4
|
-
|
|
5
|
-
-- Setup
|
|
6
|
-
select pgflow.create_flow('test_flow');
|
|
7
|
-
select pgflow.add_step('test_flow', 'first_step');
|
|
8
|
-
select pgflow.add_step('test_flow', 'second_step', array['first_step']);
|
|
9
|
-
|
|
10
|
-
-- Test
|
|
11
|
-
select pgflow.add_step('test_flow', 'third_step', array['second_step']);
|
|
12
|
-
select
|
|
13
|
-
pgflow.add_step('test_flow', 'fourth_step', array['second_step', 'third_step']);
|
|
14
|
-
select results_eq(
|
|
15
|
-
$$
|
|
16
|
-
SELECT step_slug FROM pgflow.steps WHERE flow_slug = 'test_flow' ORDER BY step_slug
|
|
17
|
-
$$,
|
|
18
|
-
array['first_step', 'fourth_step', 'second_step', 'third_step']::text [],
|
|
19
|
-
'All steps should be in the steps table'
|
|
20
|
-
);
|
|
21
|
-
select is(
|
|
22
|
-
(
|
|
23
|
-
select deps_count::int
|
|
24
|
-
from pgflow.steps
|
|
25
|
-
where flow_slug = 'test_flow' and step_slug = 'fourth_step'
|
|
26
|
-
),
|
|
27
|
-
2::int,
|
|
28
|
-
'deps_count should be 2 because "fourth_step" have two dependencies'
|
|
29
|
-
);
|
|
30
|
-
select set_eq(
|
|
31
|
-
$$
|
|
32
|
-
SELECT dep_slug, step_slug
|
|
33
|
-
FROM pgflow.deps
|
|
34
|
-
WHERE flow_slug = 'test_flow'
|
|
35
|
-
$$,
|
|
36
|
-
$$ VALUES
|
|
37
|
-
('first_step', 'second_step'),
|
|
38
|
-
('second_step', 'third_step'),
|
|
39
|
-
('second_step', 'fourth_step'),
|
|
40
|
-
('third_step', 'fourth_step')
|
|
41
|
-
$$,
|
|
42
|
-
'All dependencies should be correctly recorded'
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
select * from finish();
|
|
46
|
-
rollback;
|