@tanstack/workflow-store-drizzle-postgres 0.0.1 → 0.0.3
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/README.md +15 -1
- package/SCHEMA_MIGRATIONS.md +85 -0
- package/dist/index.cjs +18 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -2
- package/dist/migrations.cjs +23 -0
- package/dist/migrations.cjs.map +1 -0
- package/dist/migrations.d.cts +16 -0
- package/dist/migrations.d.ts +16 -0
- package/dist/migrations.js +21 -0
- package/dist/migrations.js.map +1 -0
- package/dist/schema-contract.cjs +169 -0
- package/dist/schema-contract.cjs.map +1 -0
- package/dist/schema-contract.d.cts +22 -0
- package/dist/schema-contract.d.ts +22 -0
- package/dist/schema-contract.js +165 -0
- package/dist/schema-contract.js.map +1 -0
- package/dist/store.cjs +59 -147
- package/dist/store.cjs.map +1 -1
- package/dist/store.d.cts +2 -12
- package/dist/store.d.ts +2 -12
- package/dist/store.js +52 -139
- package/dist/store.js.map +1 -1
- package/dist/tables.cjs +103 -0
- package/dist/tables.cjs.map +1 -0
- package/dist/tables.d.cts +1259 -0
- package/dist/tables.d.ts +1259 -0
- package/dist/tables.js +95 -0
- package/dist/tables.js.map +1 -0
- package/migrations/0000_workflow_store.sql +136 -0
- package/package.json +4 -2
- package/src/index.ts +25 -3
- package/src/migrations.ts +34 -0
- package/src/schema-contract.ts +208 -0
- package/src/store.ts +97 -162
- package/src/tables.ts +149 -0
package/dist/tables.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { bigint, boolean, index, integer, jsonb, pgTable, primaryKey, text } from "drizzle-orm/pg-core";
|
|
2
|
+
|
|
3
|
+
//#region src/tables.ts
|
|
4
|
+
const workflowSchemaMigrations = pgTable("workflow_schema_migrations", {
|
|
5
|
+
migrationId: text("migration_id").primaryKey(),
|
|
6
|
+
packageName: text("package_name").notNull(),
|
|
7
|
+
packageVersion: text("package_version"),
|
|
8
|
+
appliedAt: bigint("applied_at", { mode: "number" }).notNull()
|
|
9
|
+
});
|
|
10
|
+
const workflowRuns = pgTable("workflow_runs", {
|
|
11
|
+
runId: text("run_id").primaryKey(),
|
|
12
|
+
workflowId: text("workflow_id").notNull(),
|
|
13
|
+
workflowVersion: text("workflow_version"),
|
|
14
|
+
status: text("status").notNull(),
|
|
15
|
+
input: jsonb("input").notNull(),
|
|
16
|
+
output: jsonb("output"),
|
|
17
|
+
error: jsonb("error"),
|
|
18
|
+
awaiting: jsonb("awaiting"),
|
|
19
|
+
waitingFor: jsonb("waiting_for"),
|
|
20
|
+
pendingApproval: jsonb("pending_approval"),
|
|
21
|
+
wakeAt: bigint("wake_at", { mode: "number" }),
|
|
22
|
+
leaseOwner: text("lease_owner"),
|
|
23
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
24
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
25
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull()
|
|
26
|
+
}, (table) => [index("workflow_runs_status_idx").on(table.status, table.updatedAt), index("workflow_runs_lease_idx").on(table.status, table.leaseExpiresAt)]);
|
|
27
|
+
const workflowRunStates = pgTable("workflow_run_states", {
|
|
28
|
+
runId: text("run_id").primaryKey(),
|
|
29
|
+
workflowId: text("workflow_id").notNull(),
|
|
30
|
+
workflowVersion: text("workflow_version"),
|
|
31
|
+
status: text("status").notNull(),
|
|
32
|
+
input: jsonb("input").notNull(),
|
|
33
|
+
output: jsonb("output"),
|
|
34
|
+
error: jsonb("error"),
|
|
35
|
+
awaiting: jsonb("awaiting"),
|
|
36
|
+
waitingFor: jsonb("waiting_for"),
|
|
37
|
+
pendingApproval: jsonb("pending_approval"),
|
|
38
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull(),
|
|
39
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull()
|
|
40
|
+
});
|
|
41
|
+
const workflowEventLocks = pgTable("workflow_event_locks", {
|
|
42
|
+
runId: text("run_id").primaryKey(),
|
|
43
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull()
|
|
44
|
+
});
|
|
45
|
+
const workflowEvents = pgTable("workflow_events", {
|
|
46
|
+
runId: text("run_id").notNull(),
|
|
47
|
+
eventIndex: integer("event_index").notNull(),
|
|
48
|
+
eventType: text("event_type").notNull(),
|
|
49
|
+
stepId: text("step_id"),
|
|
50
|
+
event: jsonb("event").notNull(),
|
|
51
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull()
|
|
52
|
+
}, (table) => [primaryKey({ columns: [table.runId, table.eventIndex] }), index("workflow_events_type_idx").on(table.runId, table.eventType)]);
|
|
53
|
+
const workflowTimers = pgTable("workflow_timers", {
|
|
54
|
+
runId: text("run_id").notNull(),
|
|
55
|
+
signalId: text("signal_id").notNull(),
|
|
56
|
+
workflowId: text("workflow_id").notNull(),
|
|
57
|
+
workflowVersion: text("workflow_version"),
|
|
58
|
+
wakeAt: bigint("wake_at", { mode: "number" }).notNull(),
|
|
59
|
+
leaseOwner: text("lease_owner"),
|
|
60
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" })
|
|
61
|
+
}, (table) => [primaryKey({ columns: [table.runId, table.signalId] }), index("workflow_timers_due_idx").on(table.wakeAt, table.leaseExpiresAt)]);
|
|
62
|
+
const workflowSignalDeliveries = pgTable("workflow_signal_deliveries", {
|
|
63
|
+
runId: text("run_id").notNull(),
|
|
64
|
+
signalId: text("signal_id").notNull(),
|
|
65
|
+
createdAt: bigint("created_at", { mode: "number" }).notNull()
|
|
66
|
+
}, (table) => [primaryKey({ columns: [table.runId, table.signalId] })]);
|
|
67
|
+
const workflowSchedules = pgTable("workflow_schedules", {
|
|
68
|
+
scheduleId: text("schedule_id").primaryKey(),
|
|
69
|
+
workflowId: text("workflow_id").notNull(),
|
|
70
|
+
workflowVersion: text("workflow_version"),
|
|
71
|
+
schedule: jsonb("schedule").notNull(),
|
|
72
|
+
overlapPolicy: text("overlap_policy").notNull(),
|
|
73
|
+
input: jsonb("input"),
|
|
74
|
+
nextFireAt: bigint("next_fire_at", { mode: "number" }),
|
|
75
|
+
enabled: boolean("enabled").notNull(),
|
|
76
|
+
updatedAt: bigint("updated_at", { mode: "number" }).notNull()
|
|
77
|
+
}, (table) => [index("workflow_schedules_due_idx").on(table.enabled, table.nextFireAt)]);
|
|
78
|
+
const workflowScheduleBuckets = pgTable("workflow_schedule_buckets", {
|
|
79
|
+
scheduleId: text("schedule_id").notNull(),
|
|
80
|
+
bucketId: text("bucket_id").notNull(),
|
|
81
|
+
workflowId: text("workflow_id").notNull(),
|
|
82
|
+
workflowVersion: text("workflow_version"),
|
|
83
|
+
runId: text("run_id").notNull(),
|
|
84
|
+
fireAt: bigint("fire_at", { mode: "number" }).notNull(),
|
|
85
|
+
input: jsonb("input"),
|
|
86
|
+
overlapPolicy: text("overlap_policy").notNull(),
|
|
87
|
+
status: text("status").notNull(),
|
|
88
|
+
leaseOwner: text("lease_owner"),
|
|
89
|
+
leaseExpiresAt: bigint("lease_expires_at", { mode: "number" }),
|
|
90
|
+
startedAt: bigint("started_at", { mode: "number" })
|
|
91
|
+
}, (table) => [primaryKey({ columns: [table.scheduleId, table.bucketId] }), index("workflow_schedule_buckets_lease_idx").on(table.status, table.fireAt, table.leaseExpiresAt)]);
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
export { workflowEventLocks, workflowEvents, workflowRunStates, workflowRuns, workflowScheduleBuckets, workflowSchedules, workflowSchemaMigrations, workflowSignalDeliveries, workflowTimers };
|
|
95
|
+
//# sourceMappingURL=tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.js","names":[],"sources":["../src/tables.ts"],"sourcesContent":["import {\n bigint,\n boolean,\n index,\n integer,\n jsonb,\n pgTable,\n primaryKey,\n text,\n} from 'drizzle-orm/pg-core'\n\nexport const workflowSchemaMigrations = pgTable('workflow_schema_migrations', {\n migrationId: text('migration_id').primaryKey(),\n packageName: text('package_name').notNull(),\n packageVersion: text('package_version'),\n appliedAt: bigint('applied_at', { mode: 'number' }).notNull(),\n})\n\nexport const workflowRuns = pgTable(\n 'workflow_runs',\n {\n runId: text('run_id').primaryKey(),\n workflowId: text('workflow_id').notNull(),\n workflowVersion: text('workflow_version'),\n status: text('status').notNull(),\n input: jsonb('input').notNull(),\n output: jsonb('output'),\n error: jsonb('error'),\n awaiting: jsonb('awaiting'),\n waitingFor: jsonb('waiting_for'),\n pendingApproval: jsonb('pending_approval'),\n wakeAt: bigint('wake_at', { mode: 'number' }),\n leaseOwner: text('lease_owner'),\n leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),\n createdAt: bigint('created_at', { mode: 'number' }).notNull(),\n updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),\n },\n (table) => [\n index('workflow_runs_status_idx').on(table.status, table.updatedAt),\n index('workflow_runs_lease_idx').on(table.status, table.leaseExpiresAt),\n ],\n)\n\nexport const workflowRunStates = pgTable('workflow_run_states', {\n runId: text('run_id').primaryKey(),\n workflowId: text('workflow_id').notNull(),\n workflowVersion: text('workflow_version'),\n status: text('status').notNull(),\n input: jsonb('input').notNull(),\n output: jsonb('output'),\n error: jsonb('error'),\n awaiting: jsonb('awaiting'),\n waitingFor: jsonb('waiting_for'),\n pendingApproval: jsonb('pending_approval'),\n createdAt: bigint('created_at', { mode: 'number' }).notNull(),\n updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),\n})\n\nexport const workflowEventLocks = pgTable('workflow_event_locks', {\n runId: text('run_id').primaryKey(),\n createdAt: bigint('created_at', { mode: 'number' }).notNull(),\n})\n\nexport const workflowEvents = pgTable(\n 'workflow_events',\n {\n runId: text('run_id').notNull(),\n eventIndex: integer('event_index').notNull(),\n eventType: text('event_type').notNull(),\n stepId: text('step_id'),\n event: jsonb('event').notNull(),\n createdAt: bigint('created_at', { mode: 'number' }).notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.runId, table.eventIndex] }),\n index('workflow_events_type_idx').on(table.runId, table.eventType),\n ],\n)\n\nexport const workflowTimers = pgTable(\n 'workflow_timers',\n {\n runId: text('run_id').notNull(),\n signalId: text('signal_id').notNull(),\n workflowId: text('workflow_id').notNull(),\n workflowVersion: text('workflow_version'),\n wakeAt: bigint('wake_at', { mode: 'number' }).notNull(),\n leaseOwner: text('lease_owner'),\n leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),\n },\n (table) => [\n primaryKey({ columns: [table.runId, table.signalId] }),\n index('workflow_timers_due_idx').on(table.wakeAt, table.leaseExpiresAt),\n ],\n)\n\nexport const workflowSignalDeliveries = pgTable(\n 'workflow_signal_deliveries',\n {\n runId: text('run_id').notNull(),\n signalId: text('signal_id').notNull(),\n createdAt: bigint('created_at', { mode: 'number' }).notNull(),\n },\n (table) => [primaryKey({ columns: [table.runId, table.signalId] })],\n)\n\nexport const workflowSchedules = pgTable(\n 'workflow_schedules',\n {\n scheduleId: text('schedule_id').primaryKey(),\n workflowId: text('workflow_id').notNull(),\n workflowVersion: text('workflow_version'),\n schedule: jsonb('schedule').notNull(),\n overlapPolicy: text('overlap_policy').notNull(),\n input: jsonb('input'),\n nextFireAt: bigint('next_fire_at', { mode: 'number' }),\n enabled: boolean('enabled').notNull(),\n updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),\n },\n (table) => [\n index('workflow_schedules_due_idx').on(table.enabled, table.nextFireAt),\n ],\n)\n\nexport const workflowScheduleBuckets = pgTable(\n 'workflow_schedule_buckets',\n {\n scheduleId: text('schedule_id').notNull(),\n bucketId: text('bucket_id').notNull(),\n workflowId: text('workflow_id').notNull(),\n workflowVersion: text('workflow_version'),\n runId: text('run_id').notNull(),\n fireAt: bigint('fire_at', { mode: 'number' }).notNull(),\n input: jsonb('input'),\n overlapPolicy: text('overlap_policy').notNull(),\n status: text('status').notNull(),\n leaseOwner: text('lease_owner'),\n leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),\n startedAt: bigint('started_at', { mode: 'number' }),\n },\n (table) => [\n primaryKey({ columns: [table.scheduleId, table.bucketId] }),\n index('workflow_schedule_buckets_lease_idx').on(\n table.status,\n table.fireAt,\n table.leaseExpiresAt,\n ),\n ],\n)\n"],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
create table if not exists "workflow_schema_migrations" (
|
|
2
|
+
migration_id text primary key,
|
|
3
|
+
package_name text not null,
|
|
4
|
+
package_version text,
|
|
5
|
+
applied_at bigint not null
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
create table if not exists "workflow_runs" (
|
|
9
|
+
run_id text primary key,
|
|
10
|
+
workflow_id text not null,
|
|
11
|
+
workflow_version text,
|
|
12
|
+
status text not null,
|
|
13
|
+
input jsonb not null,
|
|
14
|
+
output jsonb,
|
|
15
|
+
error jsonb,
|
|
16
|
+
awaiting jsonb,
|
|
17
|
+
waiting_for jsonb,
|
|
18
|
+
pending_approval jsonb,
|
|
19
|
+
wake_at bigint,
|
|
20
|
+
lease_owner text,
|
|
21
|
+
lease_expires_at bigint,
|
|
22
|
+
created_at bigint not null,
|
|
23
|
+
updated_at bigint not null
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
alter table "workflow_runs" add column if not exists awaiting jsonb;
|
|
27
|
+
|
|
28
|
+
create index if not exists "workflow_runs_status_idx"
|
|
29
|
+
on "workflow_runs" (status, updated_at);
|
|
30
|
+
|
|
31
|
+
create index if not exists "workflow_runs_lease_idx"
|
|
32
|
+
on "workflow_runs" (status, lease_expires_at);
|
|
33
|
+
|
|
34
|
+
create table if not exists "workflow_run_states" (
|
|
35
|
+
run_id text primary key,
|
|
36
|
+
workflow_id text not null,
|
|
37
|
+
workflow_version text,
|
|
38
|
+
status text not null,
|
|
39
|
+
input jsonb not null,
|
|
40
|
+
output jsonb,
|
|
41
|
+
error jsonb,
|
|
42
|
+
awaiting jsonb,
|
|
43
|
+
waiting_for jsonb,
|
|
44
|
+
pending_approval jsonb,
|
|
45
|
+
created_at bigint not null,
|
|
46
|
+
updated_at bigint not null
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
alter table "workflow_run_states" add column if not exists awaiting jsonb;
|
|
50
|
+
|
|
51
|
+
create table if not exists "workflow_event_locks" (
|
|
52
|
+
run_id text primary key,
|
|
53
|
+
created_at bigint not null
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
create table if not exists "workflow_events" (
|
|
57
|
+
run_id text not null,
|
|
58
|
+
event_index integer not null,
|
|
59
|
+
event_type text not null,
|
|
60
|
+
step_id text,
|
|
61
|
+
event jsonb not null,
|
|
62
|
+
created_at bigint not null,
|
|
63
|
+
primary key (run_id, event_index)
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
create index if not exists "workflow_events_type_idx"
|
|
67
|
+
on "workflow_events" (run_id, event_type);
|
|
68
|
+
|
|
69
|
+
create table if not exists "workflow_timers" (
|
|
70
|
+
run_id text not null,
|
|
71
|
+
signal_id text not null,
|
|
72
|
+
workflow_id text not null,
|
|
73
|
+
workflow_version text,
|
|
74
|
+
wake_at bigint not null,
|
|
75
|
+
lease_owner text,
|
|
76
|
+
lease_expires_at bigint,
|
|
77
|
+
primary key (run_id, signal_id)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
create index if not exists "workflow_timers_due_idx"
|
|
81
|
+
on "workflow_timers" (wake_at, lease_expires_at);
|
|
82
|
+
|
|
83
|
+
create table if not exists "workflow_signal_deliveries" (
|
|
84
|
+
run_id text not null,
|
|
85
|
+
signal_id text not null,
|
|
86
|
+
created_at bigint not null,
|
|
87
|
+
primary key (run_id, signal_id)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
create table if not exists "workflow_schedules" (
|
|
91
|
+
schedule_id text primary key,
|
|
92
|
+
workflow_id text not null,
|
|
93
|
+
workflow_version text,
|
|
94
|
+
schedule jsonb not null,
|
|
95
|
+
overlap_policy text not null,
|
|
96
|
+
input jsonb,
|
|
97
|
+
next_fire_at bigint,
|
|
98
|
+
enabled boolean not null,
|
|
99
|
+
updated_at bigint not null
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
create index if not exists "workflow_schedules_due_idx"
|
|
103
|
+
on "workflow_schedules" (enabled, next_fire_at);
|
|
104
|
+
|
|
105
|
+
create table if not exists "workflow_schedule_buckets" (
|
|
106
|
+
schedule_id text not null,
|
|
107
|
+
bucket_id text not null,
|
|
108
|
+
workflow_id text not null,
|
|
109
|
+
workflow_version text,
|
|
110
|
+
run_id text not null,
|
|
111
|
+
fire_at bigint not null,
|
|
112
|
+
input jsonb,
|
|
113
|
+
overlap_policy text not null,
|
|
114
|
+
status text not null,
|
|
115
|
+
lease_owner text,
|
|
116
|
+
lease_expires_at bigint,
|
|
117
|
+
started_at bigint,
|
|
118
|
+
primary key (schedule_id, bucket_id)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
create index if not exists "workflow_schedule_buckets_lease_idx"
|
|
122
|
+
on "workflow_schedule_buckets" (status, fire_at, lease_expires_at);
|
|
123
|
+
|
|
124
|
+
insert into "workflow_schema_migrations" (
|
|
125
|
+
migration_id,
|
|
126
|
+
package_name,
|
|
127
|
+
package_version,
|
|
128
|
+
applied_at
|
|
129
|
+
)
|
|
130
|
+
values (
|
|
131
|
+
'0000_workflow_store',
|
|
132
|
+
'@tanstack/workflow-store-drizzle-postgres',
|
|
133
|
+
null,
|
|
134
|
+
(extract(epoch from now()) * 1000)::bigint
|
|
135
|
+
)
|
|
136
|
+
on conflict (migration_id) do nothing;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/workflow-store-drizzle-postgres",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Drizzle/Postgres durable execution store for TanStack Workflow.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,7 +48,9 @@
|
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist/",
|
|
51
|
-
"
|
|
51
|
+
"migrations/",
|
|
52
|
+
"src",
|
|
53
|
+
"SCHEMA_MIGRATIONS.md"
|
|
52
54
|
],
|
|
53
55
|
"dependencies": {
|
|
54
56
|
"@tanstack/workflow-core": "workspace:*",
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
+
export { createDrizzlePostgresWorkflowStore } from './store'
|
|
1
2
|
export {
|
|
2
|
-
createDrizzlePostgresWorkflowStore,
|
|
3
3
|
defaultDrizzlePostgresWorkflowStoreTables,
|
|
4
|
-
|
|
4
|
+
getDrizzlePostgresWorkflowStoreSchemaStatements,
|
|
5
|
+
resolveDrizzlePostgresWorkflowStoreTables,
|
|
6
|
+
} from './schema-contract'
|
|
7
|
+
export {
|
|
8
|
+
drizzlePostgresWorkflowStoreSchemaVersion,
|
|
9
|
+
getDrizzlePostgresWorkflowStoreMigrations,
|
|
10
|
+
getDrizzlePostgresWorkflowStoreMigrationSql,
|
|
11
|
+
} from './migrations'
|
|
12
|
+
export {
|
|
13
|
+
workflowEventLocks,
|
|
14
|
+
workflowEvents,
|
|
15
|
+
workflowRuns,
|
|
16
|
+
workflowRunStates,
|
|
17
|
+
workflowScheduleBuckets,
|
|
18
|
+
workflowSchedules,
|
|
19
|
+
workflowSchemaMigrations,
|
|
20
|
+
workflowSignalDeliveries,
|
|
21
|
+
workflowTimers,
|
|
22
|
+
} from './tables'
|
|
5
23
|
export type {
|
|
6
24
|
DrizzlePostgresDatabase,
|
|
7
25
|
DrizzlePostgresWorkflowStore,
|
|
8
26
|
DrizzlePostgresWorkflowStoreOptions,
|
|
9
|
-
DrizzlePostgresWorkflowStoreTables,
|
|
10
27
|
} from './store'
|
|
28
|
+
export type { DrizzlePostgresWorkflowStoreMigration } from './migrations'
|
|
29
|
+
export type {
|
|
30
|
+
DrizzlePostgresWorkflowStoreSchemaOptions,
|
|
31
|
+
DrizzlePostgresWorkflowStoreTables,
|
|
32
|
+
} from './schema-contract'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getDrizzlePostgresWorkflowStoreSchemaStatements } from './schema-contract'
|
|
2
|
+
import type { DrizzlePostgresWorkflowStoreSchemaOptions } from './schema-contract'
|
|
3
|
+
|
|
4
|
+
export interface DrizzlePostgresWorkflowStoreMigration {
|
|
5
|
+
id: string
|
|
6
|
+
name: string
|
|
7
|
+
order: number
|
|
8
|
+
statements: Array<string>
|
|
9
|
+
sql: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const drizzlePostgresWorkflowStoreSchemaVersion = '0000_workflow_store'
|
|
13
|
+
|
|
14
|
+
export function getDrizzlePostgresWorkflowStoreMigrations(
|
|
15
|
+
options?: DrizzlePostgresWorkflowStoreSchemaOptions,
|
|
16
|
+
): Array<DrizzlePostgresWorkflowStoreMigration> {
|
|
17
|
+
const statements = getDrizzlePostgresWorkflowStoreSchemaStatements(options)
|
|
18
|
+
|
|
19
|
+
return [
|
|
20
|
+
{
|
|
21
|
+
id: '0000_workflow_store',
|
|
22
|
+
name: 'Create TanStack Workflow Drizzle/Postgres store tables',
|
|
23
|
+
order: 0,
|
|
24
|
+
statements,
|
|
25
|
+
sql: `${statements.join(';\n\n')};\n`,
|
|
26
|
+
},
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getDrizzlePostgresWorkflowStoreMigrationSql(
|
|
31
|
+
options?: DrizzlePostgresWorkflowStoreSchemaOptions,
|
|
32
|
+
): string {
|
|
33
|
+
return getDrizzlePostgresWorkflowStoreMigrations(options)[0]!.sql
|
|
34
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
export interface DrizzlePostgresWorkflowStoreTables {
|
|
2
|
+
schemaMigrations: string
|
|
3
|
+
runs: string
|
|
4
|
+
runStates: string
|
|
5
|
+
eventLocks: string
|
|
6
|
+
events: string
|
|
7
|
+
timers: string
|
|
8
|
+
signalDeliveries: string
|
|
9
|
+
schedules: string
|
|
10
|
+
scheduleBuckets: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DrizzlePostgresWorkflowStoreSchemaOptions {
|
|
14
|
+
schema?: string
|
|
15
|
+
tables?: Partial<DrizzlePostgresWorkflowStoreTables>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const defaultDrizzlePostgresWorkflowStoreTables: DrizzlePostgresWorkflowStoreTables =
|
|
19
|
+
{
|
|
20
|
+
schemaMigrations: 'workflow_schema_migrations',
|
|
21
|
+
runs: 'workflow_runs',
|
|
22
|
+
runStates: 'workflow_run_states',
|
|
23
|
+
eventLocks: 'workflow_event_locks',
|
|
24
|
+
events: 'workflow_events',
|
|
25
|
+
timers: 'workflow_timers',
|
|
26
|
+
signalDeliveries: 'workflow_signal_deliveries',
|
|
27
|
+
schedules: 'workflow_schedules',
|
|
28
|
+
scheduleBuckets: 'workflow_schedule_buckets',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function resolveDrizzlePostgresWorkflowStoreTables(
|
|
32
|
+
tables?: Partial<DrizzlePostgresWorkflowStoreTables>,
|
|
33
|
+
): DrizzlePostgresWorkflowStoreTables {
|
|
34
|
+
return {
|
|
35
|
+
...defaultDrizzlePostgresWorkflowStoreTables,
|
|
36
|
+
...tables,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getDrizzlePostgresWorkflowStoreSchemaStatements(
|
|
41
|
+
options: DrizzlePostgresWorkflowStoreSchemaOptions = {},
|
|
42
|
+
): Array<string> {
|
|
43
|
+
const tables = resolveDrizzlePostgresWorkflowStoreTables(options.tables)
|
|
44
|
+
const schemaMigrations = qualifiedTableName(
|
|
45
|
+
options.schema,
|
|
46
|
+
tables.schemaMigrations,
|
|
47
|
+
)
|
|
48
|
+
const runs = qualifiedTableName(options.schema, tables.runs)
|
|
49
|
+
const runStates = qualifiedTableName(options.schema, tables.runStates)
|
|
50
|
+
const eventLocks = qualifiedTableName(options.schema, tables.eventLocks)
|
|
51
|
+
const events = qualifiedTableName(options.schema, tables.events)
|
|
52
|
+
const timers = qualifiedTableName(options.schema, tables.timers)
|
|
53
|
+
const signalDeliveries = qualifiedTableName(
|
|
54
|
+
options.schema,
|
|
55
|
+
tables.signalDeliveries,
|
|
56
|
+
)
|
|
57
|
+
const schedules = qualifiedTableName(options.schema, tables.schedules)
|
|
58
|
+
const scheduleBuckets = qualifiedTableName(
|
|
59
|
+
options.schema,
|
|
60
|
+
tables.scheduleBuckets,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return [
|
|
64
|
+
...(options.schema
|
|
65
|
+
? [`create schema if not exists ${quoteIdent(options.schema)}`]
|
|
66
|
+
: []),
|
|
67
|
+
`create table if not exists ${schemaMigrations} (
|
|
68
|
+
migration_id text primary key,
|
|
69
|
+
package_name text not null,
|
|
70
|
+
package_version text,
|
|
71
|
+
applied_at bigint not null
|
|
72
|
+
)`,
|
|
73
|
+
`create table if not exists ${runs} (
|
|
74
|
+
run_id text primary key,
|
|
75
|
+
workflow_id text not null,
|
|
76
|
+
workflow_version text,
|
|
77
|
+
status text not null,
|
|
78
|
+
input jsonb not null,
|
|
79
|
+
output jsonb,
|
|
80
|
+
error jsonb,
|
|
81
|
+
awaiting jsonb,
|
|
82
|
+
waiting_for jsonb,
|
|
83
|
+
pending_approval jsonb,
|
|
84
|
+
wake_at bigint,
|
|
85
|
+
lease_owner text,
|
|
86
|
+
lease_expires_at bigint,
|
|
87
|
+
created_at bigint not null,
|
|
88
|
+
updated_at bigint not null
|
|
89
|
+
)`,
|
|
90
|
+
`alter table ${runs} add column if not exists awaiting jsonb`,
|
|
91
|
+
`create index if not exists ${quoteIdent(`${tables.runs}_status_idx`)}
|
|
92
|
+
on ${runs} (status, updated_at)`,
|
|
93
|
+
`create index if not exists ${quoteIdent(`${tables.runs}_lease_idx`)}
|
|
94
|
+
on ${runs} (status, lease_expires_at)`,
|
|
95
|
+
`create table if not exists ${runStates} (
|
|
96
|
+
run_id text primary key,
|
|
97
|
+
workflow_id text not null,
|
|
98
|
+
workflow_version text,
|
|
99
|
+
status text not null,
|
|
100
|
+
input jsonb not null,
|
|
101
|
+
output jsonb,
|
|
102
|
+
error jsonb,
|
|
103
|
+
awaiting jsonb,
|
|
104
|
+
waiting_for jsonb,
|
|
105
|
+
pending_approval jsonb,
|
|
106
|
+
created_at bigint not null,
|
|
107
|
+
updated_at bigint not null
|
|
108
|
+
)`,
|
|
109
|
+
`alter table ${runStates} add column if not exists awaiting jsonb`,
|
|
110
|
+
`create table if not exists ${eventLocks} (
|
|
111
|
+
run_id text primary key,
|
|
112
|
+
created_at bigint not null
|
|
113
|
+
)`,
|
|
114
|
+
`create table if not exists ${events} (
|
|
115
|
+
run_id text not null,
|
|
116
|
+
event_index integer not null,
|
|
117
|
+
event_type text not null,
|
|
118
|
+
step_id text,
|
|
119
|
+
event jsonb not null,
|
|
120
|
+
created_at bigint not null,
|
|
121
|
+
primary key (run_id, event_index)
|
|
122
|
+
)`,
|
|
123
|
+
`create index if not exists ${quoteIdent(`${tables.events}_type_idx`)}
|
|
124
|
+
on ${events} (run_id, event_type)`,
|
|
125
|
+
`create table if not exists ${timers} (
|
|
126
|
+
run_id text not null,
|
|
127
|
+
signal_id text not null,
|
|
128
|
+
workflow_id text not null,
|
|
129
|
+
workflow_version text,
|
|
130
|
+
wake_at bigint not null,
|
|
131
|
+
lease_owner text,
|
|
132
|
+
lease_expires_at bigint,
|
|
133
|
+
primary key (run_id, signal_id)
|
|
134
|
+
)`,
|
|
135
|
+
`create index if not exists ${quoteIdent(`${tables.timers}_due_idx`)}
|
|
136
|
+
on ${timers} (wake_at, lease_expires_at)`,
|
|
137
|
+
`create table if not exists ${signalDeliveries} (
|
|
138
|
+
run_id text not null,
|
|
139
|
+
signal_id text not null,
|
|
140
|
+
created_at bigint not null,
|
|
141
|
+
primary key (run_id, signal_id)
|
|
142
|
+
)`,
|
|
143
|
+
`create table if not exists ${schedules} (
|
|
144
|
+
schedule_id text primary key,
|
|
145
|
+
workflow_id text not null,
|
|
146
|
+
workflow_version text,
|
|
147
|
+
schedule jsonb not null,
|
|
148
|
+
overlap_policy text not null,
|
|
149
|
+
input jsonb,
|
|
150
|
+
next_fire_at bigint,
|
|
151
|
+
enabled boolean not null,
|
|
152
|
+
updated_at bigint not null
|
|
153
|
+
)`,
|
|
154
|
+
`create index if not exists ${quoteIdent(`${tables.schedules}_due_idx`)}
|
|
155
|
+
on ${schedules} (enabled, next_fire_at)`,
|
|
156
|
+
`create table if not exists ${scheduleBuckets} (
|
|
157
|
+
schedule_id text not null,
|
|
158
|
+
bucket_id text not null,
|
|
159
|
+
workflow_id text not null,
|
|
160
|
+
workflow_version text,
|
|
161
|
+
run_id text not null,
|
|
162
|
+
fire_at bigint not null,
|
|
163
|
+
input jsonb,
|
|
164
|
+
overlap_policy text not null,
|
|
165
|
+
status text not null,
|
|
166
|
+
lease_owner text,
|
|
167
|
+
lease_expires_at bigint,
|
|
168
|
+
started_at bigint,
|
|
169
|
+
primary key (schedule_id, bucket_id)
|
|
170
|
+
)`,
|
|
171
|
+
`create index if not exists ${quoteIdent(
|
|
172
|
+
`${tables.scheduleBuckets}_lease_idx`,
|
|
173
|
+
)}
|
|
174
|
+
on ${scheduleBuckets} (status, fire_at, lease_expires_at)`,
|
|
175
|
+
`insert into ${schemaMigrations} (
|
|
176
|
+
migration_id,
|
|
177
|
+
package_name,
|
|
178
|
+
package_version,
|
|
179
|
+
applied_at
|
|
180
|
+
)
|
|
181
|
+
values (
|
|
182
|
+
'0000_workflow_store',
|
|
183
|
+
'@tanstack/workflow-store-drizzle-postgres',
|
|
184
|
+
null,
|
|
185
|
+
(extract(epoch from now()) * 1000)::bigint
|
|
186
|
+
)
|
|
187
|
+
on conflict (migration_id) do nothing`,
|
|
188
|
+
].map(normalizeSqlStatement)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function qualifiedTableName(schema: string | undefined, table: string) {
|
|
192
|
+
return schema
|
|
193
|
+
? `${quoteIdent(schema)}.${quoteIdent(table)}`
|
|
194
|
+
: quoteIdent(table)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function quoteIdent(identifier: string) {
|
|
198
|
+
return `"${identifier.replaceAll('"', '""')}"`
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function normalizeSqlStatement(statement: string) {
|
|
202
|
+
return statement
|
|
203
|
+
.split('\n')
|
|
204
|
+
.map((line, index) =>
|
|
205
|
+
index === 0 ? line.trimEnd() : line.replace(/^ {4}/, '').trimEnd(),
|
|
206
|
+
)
|
|
207
|
+
.join('\n')
|
|
208
|
+
}
|