@sixb/pg 0.1.17 → 0.1.19
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/dist/index.js +237 -276
- package/dist/index.js.map +4 -4
- package/dist/migrations.d.ts.map +1 -1
- package/dist/pg-action-run-storage.d.ts +2 -9
- package/dist/pg-action-run-storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/migrations/061-terminal-action-runs.sql +150 -0
- package/src/migrations.ts +2 -0
- package/src/pg-action-run-storage.ts +97 -374
package/dist/migrations.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAqH3B,OAAO,KAAK,EAAe,GAAG,EAAa,MAAM,aAAa,CAAA;AAG9D,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC;AAED,eAAO,MAAM,2BAA2B,wBAAwB,CAAA;AAEhE,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,wBAAwB,CAAC,CAE1F;AAED,wBAAgB,MAAM,CACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/D,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,wBAAwB,CAAC,CAEzC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,GACjB,SAAS,eAAe,EAAE,CAQ5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,wBAAwB,CAAC,CAAA;CAC5D,GAAG,eAAe,CAqBlB;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxF;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AAuKD,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAGV,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAqH3B,OAAO,KAAK,EAAe,GAAG,EAAa,MAAM,aAAa,CAAA;AAG9D,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC;AAED,eAAO,MAAM,2BAA2B,wBAAwB,CAAA;AAEhE,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,wBAAwB,CAAC,CAE1F;AAED,wBAAgB,MAAM,CACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/D,OAAO,GAAE,oBAAyB,GACjC,aAAa,CAAC,wBAAwB,CAAC,CAEzC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,MAAM,GACjB,SAAS,eAAe,EAAE,CAQ5B;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,wBAAwB,CAAC,CAAA;CAC5D,GAAG,eAAe,CAqBlB;AAED,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxF;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKrD;AAuKD,eAAO,MAAM,yBAAyB,wCAiEpC,CAAA"}
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
import type { ActionRunRecord, ActionRunStorage,
|
|
1
|
+
import type { ActionRunRecord, ActionRunStorage, ExecutionStorage, ListActionRunsInput, ListActionRunsResult, RecordActionEffectsInput, RecordActionRunInput } from "@sixb/core/storage";
|
|
2
2
|
import { type PgStoreClient } from "./transactions";
|
|
3
3
|
export declare class PgActionRunStorage implements ActionRunStorage {
|
|
4
4
|
private readonly sql;
|
|
5
5
|
private readonly executions;
|
|
6
6
|
constructor(sql: PgStoreClient, executions: ExecutionStorage);
|
|
7
|
-
|
|
8
|
-
queue(input: QueueActionRunInput): Promise<ActionRunRecord>;
|
|
9
|
-
private requeueAfterEnqueueFailure;
|
|
10
|
-
start(input: StartActionRunInput): Promise<ActionRunRecord>;
|
|
11
|
-
enterPhase(input: EnterActionRunPhaseInput): Promise<ActionRunRecord>;
|
|
12
|
-
recordWriteback(input: RecordActionWritebackInput): Promise<ActionRunRecord>;
|
|
7
|
+
record(input: RecordActionRunInput): Promise<ActionRunRecord>;
|
|
13
8
|
recordEffects(input: RecordActionEffectsInput): Promise<ActionRunRecord>;
|
|
14
|
-
finish(input: FinishActionRunInput): Promise<ActionRunRecord>;
|
|
15
9
|
getById(params: {
|
|
16
10
|
projectId: string;
|
|
17
11
|
id: string;
|
|
18
12
|
}): Promise<ActionRunRecord | null>;
|
|
19
13
|
list(input: ListActionRunsInput): Promise<ListActionRunsResult>;
|
|
20
|
-
private requireRunningRun;
|
|
21
14
|
}
|
|
22
15
|
//# sourceMappingURL=pg-action-run-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-action-run-storage.d.ts","sourceRoot":"","sources":["../src/pg-action-run-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pg-action-run-storage.d.ts","sourceRoot":"","sources":["../src/pg-action-run-storage.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAIV,eAAe,EAEf,gBAAgB,EAEhB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,gBAAgB,CAAA;AAErE,qBAAa,kBAAmB,YAAW,gBAAgB;IAEvD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,gBAAgB;IAGzC,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC;IAuE7D,aAAa,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC;IA2BxE,OAAO,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IASnF,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAiHtE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sixb/pg",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "PostgreSQL storage provider for Sixb",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sixb",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"postgres": "^3.4.5"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@sixb/core": "0.1.
|
|
43
|
+
"@sixb/core": "0.1.19"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@sixb/core": "0.1.
|
|
46
|
+
"@sixb/core": "0.1.19",
|
|
47
47
|
"@types/bun": "latest",
|
|
48
48
|
"typescript": "^5.7.0"
|
|
49
49
|
},
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
-- Actions run in the request that asks for them and record their run once, when it ends. No run
|
|
2
|
+
-- is queued, running, or cancelled any more, and every run has started and finished.
|
|
3
|
+
|
|
4
|
+
-- A run left running after its edits committed, as a crash between the commit and the end of the
|
|
5
|
+
-- run left it, succeeded: its edits and their outbox facts are in the commit. A run that stopped
|
|
6
|
+
-- during its effects keeps that phase, and records effects that never ended.
|
|
7
|
+
UPDATE action_runs AS run
|
|
8
|
+
SET
|
|
9
|
+
status = 'succeeded',
|
|
10
|
+
error = NULL,
|
|
11
|
+
finished_at = committed.committed_at,
|
|
12
|
+
phase = CASE WHEN run.phase = 'effects' THEN 'effects' ELSE 'commit' END,
|
|
13
|
+
effects_status = CASE
|
|
14
|
+
WHEN run.phase = 'effects' AND run.effects_status IS NULL THEN 'failed'
|
|
15
|
+
ELSE run.effects_status
|
|
16
|
+
END,
|
|
17
|
+
effects_completed_at = CASE
|
|
18
|
+
WHEN run.phase = 'effects' AND run.effects_status IS NULL THEN now()
|
|
19
|
+
ELSE run.effects_completed_at
|
|
20
|
+
END,
|
|
21
|
+
effects_error = CASE
|
|
22
|
+
WHEN run.phase = 'effects' AND run.effects_status IS NULL THEN jsonb_build_object(
|
|
23
|
+
'code', 'internal.unexpected',
|
|
24
|
+
'message', 'Abandoned: Actions now run synchronously; these effects never finished.',
|
|
25
|
+
'retryable', false,
|
|
26
|
+
'at', to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),
|
|
27
|
+
'details', jsonb_build_object('actionId', run.action_id, 'runId', run.id, 'phase', 'effects')
|
|
28
|
+
)
|
|
29
|
+
ELSE run.effects_error
|
|
30
|
+
END
|
|
31
|
+
FROM ontology_commits AS committed
|
|
32
|
+
WHERE run.status IN ('queued', 'running')
|
|
33
|
+
AND committed.origin_kind = 'action'
|
|
34
|
+
AND committed.project_id = run.project_id
|
|
35
|
+
AND committed.origin_run_id = run.id;
|
|
36
|
+
|
|
37
|
+
-- Any other run left queued or running never finished, and nothing will resume it.
|
|
38
|
+
UPDATE action_runs
|
|
39
|
+
SET
|
|
40
|
+
status = 'failed',
|
|
41
|
+
finished_at = now(),
|
|
42
|
+
error = jsonb_build_object(
|
|
43
|
+
'code', 'internal.unexpected',
|
|
44
|
+
'message', 'Abandoned: Actions now run synchronously; this run never finished.',
|
|
45
|
+
'retryable', false,
|
|
46
|
+
'at', to_char(now() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),
|
|
47
|
+
'details', jsonb_build_object('actionId', action_id, 'runId', id)
|
|
48
|
+
)
|
|
49
|
+
WHERE status IN ('queued', 'running');
|
|
50
|
+
|
|
51
|
+
-- A cancelled run failed: it keeps the failure it recorded.
|
|
52
|
+
UPDATE action_runs SET status = 'failed' WHERE status = 'cancelled';
|
|
53
|
+
|
|
54
|
+
-- Every failed run carries a failure. One recorded before failures were kept explains itself.
|
|
55
|
+
UPDATE action_runs
|
|
56
|
+
SET error = jsonb_build_object(
|
|
57
|
+
'code', 'internal.unexpected',
|
|
58
|
+
'message', 'This run failed before Sixb recorded why.',
|
|
59
|
+
'retryable', false,
|
|
60
|
+
'at', to_char(COALESCE(finished_at, now()) AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'),
|
|
61
|
+
'details', jsonb_build_object('actionId', action_id, 'runId', id)
|
|
62
|
+
)
|
|
63
|
+
WHERE status = 'failed' AND error IS NULL;
|
|
64
|
+
|
|
65
|
+
-- The phases `request`, `enqueue`, and `cancelled` are gone: a run that stopped in one of them
|
|
66
|
+
-- never got past validation. A run starts when it was queued at the latest.
|
|
67
|
+
UPDATE action_runs
|
|
68
|
+
SET
|
|
69
|
+
phase = CASE
|
|
70
|
+
WHEN phase IN ('validation', 'writeback', 'edits', 'commit', 'effects') THEN phase
|
|
71
|
+
ELSE 'validation'
|
|
72
|
+
END,
|
|
73
|
+
started_at = COALESCE(started_at, queued_at),
|
|
74
|
+
finished_at = COALESCE(finished_at, now()),
|
|
75
|
+
writeback_completed_at = CASE
|
|
76
|
+
WHEN writeback_status IS NULL THEN NULL
|
|
77
|
+
ELSE COALESCE(writeback_completed_at, finished_at, now())
|
|
78
|
+
END,
|
|
79
|
+
effects_completed_at = CASE
|
|
80
|
+
WHEN effects_status IS NULL THEN NULL
|
|
81
|
+
ELSE COALESCE(effects_completed_at, finished_at, now())
|
|
82
|
+
END
|
|
83
|
+
WHERE phase IS NULL
|
|
84
|
+
OR phase NOT IN ('validation', 'writeback', 'edits', 'commit', 'effects')
|
|
85
|
+
OR started_at IS NULL
|
|
86
|
+
OR finished_at IS NULL
|
|
87
|
+
OR (writeback_status IS NOT NULL AND writeback_completed_at IS NULL)
|
|
88
|
+
OR (effects_status IS NOT NULL AND effects_completed_at IS NULL);
|
|
89
|
+
|
|
90
|
+
-- A failure names the phase its run ended in, and only Action codes: an enqueue failure, which no
|
|
91
|
+
-- run can meet any more, reads as the unexpected error it now is.
|
|
92
|
+
UPDATE action_runs
|
|
93
|
+
SET error = jsonb_set(
|
|
94
|
+
CASE
|
|
95
|
+
WHEN error->>'code' = 'queue.enqueue_failed'
|
|
96
|
+
THEN error || '{"code": "internal.unexpected", "retryable": false}'::jsonb
|
|
97
|
+
ELSE error
|
|
98
|
+
END,
|
|
99
|
+
'{details,phase}',
|
|
100
|
+
to_jsonb(phase)
|
|
101
|
+
)
|
|
102
|
+
WHERE error IS NOT NULL
|
|
103
|
+
AND (
|
|
104
|
+
error->'details'->>'phase' IS DISTINCT FROM phase
|
|
105
|
+
OR error->>'code' = 'queue.enqueue_failed'
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
-- The status and phase checks were unnamed. Drop exactly the two that admit the removed values.
|
|
109
|
+
DO $$
|
|
110
|
+
DECLARE lifecycle_constraint RECORD;
|
|
111
|
+
BEGIN
|
|
112
|
+
FOR lifecycle_constraint IN
|
|
113
|
+
SELECT conname
|
|
114
|
+
FROM pg_constraint
|
|
115
|
+
WHERE conrelid = 'action_runs'::regclass
|
|
116
|
+
AND contype = 'c'
|
|
117
|
+
AND (
|
|
118
|
+
pg_get_constraintdef(oid) LIKE '%''queued''%'
|
|
119
|
+
OR pg_get_constraintdef(oid) LIKE '%''enqueue''%'
|
|
120
|
+
)
|
|
121
|
+
LOOP
|
|
122
|
+
EXECUTE format('ALTER TABLE action_runs DROP CONSTRAINT %I', lifecycle_constraint.conname);
|
|
123
|
+
END LOOP;
|
|
124
|
+
END $$;
|
|
125
|
+
|
|
126
|
+
-- The listing indexes ordered runs by `COALESCE(started_at, queued_at)`.
|
|
127
|
+
DROP INDEX idx_action_runs_project_started;
|
|
128
|
+
DROP INDEX idx_action_runs_project_action_started;
|
|
129
|
+
DROP INDEX idx_action_runs_project_object_started;
|
|
130
|
+
DROP INDEX idx_action_runs_project_status_started;
|
|
131
|
+
|
|
132
|
+
ALTER TABLE action_runs
|
|
133
|
+
DROP COLUMN queued_at,
|
|
134
|
+
ALTER COLUMN phase SET NOT NULL,
|
|
135
|
+
ALTER COLUMN started_at SET NOT NULL,
|
|
136
|
+
ALTER COLUMN finished_at SET NOT NULL,
|
|
137
|
+
ADD CONSTRAINT action_runs_status_check CHECK (status IN ('succeeded', 'failed')),
|
|
138
|
+
ADD CONSTRAINT action_runs_phase_check CHECK (
|
|
139
|
+
phase IN ('validation', 'writeback', 'edits', 'commit', 'effects')
|
|
140
|
+
),
|
|
141
|
+
ADD CONSTRAINT action_runs_failure_check CHECK ((status = 'failed') = (error IS NOT NULL));
|
|
142
|
+
|
|
143
|
+
CREATE INDEX idx_action_runs_project_started
|
|
144
|
+
ON action_runs (project_id, started_at DESC);
|
|
145
|
+
CREATE INDEX idx_action_runs_project_action_started
|
|
146
|
+
ON action_runs (project_id, action_id, started_at DESC);
|
|
147
|
+
CREATE INDEX idx_action_runs_project_object_started
|
|
148
|
+
ON action_runs (project_id, object_type_id, primary_id, started_at DESC);
|
|
149
|
+
CREATE INDEX idx_action_runs_project_status_started
|
|
150
|
+
ON action_runs (project_id, status, started_at DESC);
|
package/src/migrations.ts
CHANGED
|
@@ -431,6 +431,7 @@ export const postgresStorageMigrations = defineMigrations<PostgresMigrationConte
|
|
|
431
431
|
pgSql("058-reranking-model-kind", rerankingModelKindSql),
|
|
432
432
|
pgSql("059-file-download-grants", fileDownloadGrantsSql),
|
|
433
433
|
pgSql("060-drained-source-versions", drainedSourceVersionsSql),
|
|
434
|
+
pgSql("061-terminal-action-runs", terminalActionRunsSql),
|
|
434
435
|
],
|
|
435
436
|
})
|
|
436
437
|
|
|
@@ -459,3 +460,4 @@ import fileDownloadGrantsSql from "./migrations/059-file-download-grants.sql" wi
|
|
|
459
460
|
import drainedSourceVersionsSql from "./migrations/060-drained-source-versions.sql" with {
|
|
460
461
|
type: "text",
|
|
461
462
|
}
|
|
463
|
+
import terminalActionRunsSql from "./migrations/061-terminal-action-runs.sql" with { type: "text" }
|