@tanstack/workflow-store-drizzle-postgres 0.0.2 → 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 +39 -141
- 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 +32 -133
- 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 +77 -156
- package/src/tables.ts +149 -0
package/src/store.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { LogConflictError } from '@tanstack/workflow-core'
|
|
2
2
|
import { sql } from 'drizzle-orm'
|
|
3
|
+
import {
|
|
4
|
+
getDrizzlePostgresWorkflowStoreSchemaStatements,
|
|
5
|
+
qualifiedTableName,
|
|
6
|
+
resolveDrizzlePostgresWorkflowStoreTables,
|
|
7
|
+
} from './schema-contract'
|
|
3
8
|
import type { RunState, WorkflowEvent } from '@tanstack/workflow-core'
|
|
4
9
|
import type { SQL } from 'drizzle-orm'
|
|
10
|
+
import type { DrizzlePostgresWorkflowStoreTables } from './schema-contract'
|
|
5
11
|
import type {
|
|
6
12
|
AppendEventsArgs,
|
|
7
13
|
AppendEventsResult,
|
|
@@ -50,17 +56,6 @@ export interface DrizzlePostgresDatabase {
|
|
|
50
56
|
) => Promise<TResult>
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
export interface DrizzlePostgresWorkflowStoreTables {
|
|
54
|
-
runs: string
|
|
55
|
-
runStates: string
|
|
56
|
-
eventLocks: string
|
|
57
|
-
events: string
|
|
58
|
-
timers: string
|
|
59
|
-
signalDeliveries: string
|
|
60
|
-
schedules: string
|
|
61
|
-
scheduleBuckets: string
|
|
62
|
-
}
|
|
63
|
-
|
|
64
59
|
export interface DrizzlePostgresWorkflowStoreOptions {
|
|
65
60
|
db: DrizzlePostgresDatabase
|
|
66
61
|
schema?: string
|
|
@@ -72,31 +67,19 @@ export type DrizzlePostgresWorkflowStore = WorkflowExecutionStore &
|
|
|
72
67
|
ensureSchema: () => Promise<void>
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
export const defaultDrizzlePostgresWorkflowStoreTables: DrizzlePostgresWorkflowStoreTables =
|
|
76
|
-
{
|
|
77
|
-
runs: 'workflow_runs',
|
|
78
|
-
runStates: 'workflow_run_states',
|
|
79
|
-
eventLocks: 'workflow_event_locks',
|
|
80
|
-
events: 'workflow_events',
|
|
81
|
-
timers: 'workflow_timers',
|
|
82
|
-
signalDeliveries: 'workflow_signal_deliveries',
|
|
83
|
-
schedules: 'workflow_schedules',
|
|
84
|
-
scheduleBuckets: 'workflow_schedule_buckets',
|
|
85
|
-
}
|
|
86
|
-
|
|
87
70
|
export function createDrizzlePostgresWorkflowStore(
|
|
88
71
|
options: DrizzlePostgresWorkflowStoreOptions,
|
|
89
72
|
): DrizzlePostgresWorkflowStore {
|
|
90
|
-
const tableNames =
|
|
91
|
-
...defaultDrizzlePostgresWorkflowStoreTables,
|
|
92
|
-
...options.tables,
|
|
93
|
-
}
|
|
73
|
+
const tableNames = resolveDrizzlePostgresWorkflowStoreTables(options.tables)
|
|
94
74
|
const tableSql = tableSqls(options.schema, tableNames)
|
|
95
75
|
const db = options.db
|
|
96
76
|
|
|
97
77
|
return {
|
|
98
78
|
async ensureSchema() {
|
|
99
|
-
for (const statement of
|
|
79
|
+
for (const statement of getDrizzlePostgresWorkflowStoreSchemaStatements({
|
|
80
|
+
schema: options.schema,
|
|
81
|
+
tables: tableNames,
|
|
82
|
+
})) {
|
|
100
83
|
await db.execute(sql.raw(statement))
|
|
101
84
|
}
|
|
102
85
|
},
|
|
@@ -165,6 +148,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
165
148
|
input,
|
|
166
149
|
output,
|
|
167
150
|
error,
|
|
151
|
+
awaiting,
|
|
168
152
|
waiting_for,
|
|
169
153
|
pending_approval,
|
|
170
154
|
created_at,
|
|
@@ -178,6 +162,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
178
162
|
${encodeJson(state.input)}::jsonb,
|
|
179
163
|
${encodeJsonOrNull(state.output)}::jsonb,
|
|
180
164
|
${encodeJsonOrNull(state.error)}::jsonb,
|
|
165
|
+
${encodeJsonOrNull(state.awaiting)}::jsonb,
|
|
181
166
|
${encodeJsonOrNull(state.waitingFor)}::jsonb,
|
|
182
167
|
${encodeJsonOrNull(state.pendingApproval)}::jsonb,
|
|
183
168
|
${state.createdAt},
|
|
@@ -190,6 +175,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
190
175
|
input = excluded.input,
|
|
191
176
|
output = excluded.output,
|
|
192
177
|
error = excluded.error,
|
|
178
|
+
awaiting = excluded.awaiting,
|
|
193
179
|
waiting_for = excluded.waiting_for,
|
|
194
180
|
pending_approval = excluded.pending_approval,
|
|
195
181
|
created_at = excluded.created_at,
|
|
@@ -204,6 +190,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
204
190
|
input,
|
|
205
191
|
output,
|
|
206
192
|
error,
|
|
193
|
+
awaiting,
|
|
207
194
|
waiting_for,
|
|
208
195
|
pending_approval,
|
|
209
196
|
wake_at,
|
|
@@ -218,6 +205,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
218
205
|
${encodeJson(state.input)}::jsonb,
|
|
219
206
|
${encodeJsonOrNull(state.output)}::jsonb,
|
|
220
207
|
${encodeJsonOrNull(state.error)}::jsonb,
|
|
208
|
+
${encodeJsonOrNull(state.awaiting)}::jsonb,
|
|
221
209
|
${encodeJsonOrNull(state.waitingFor)}::jsonb,
|
|
222
210
|
${encodeJsonOrNull(state.pendingApproval)}::jsonb,
|
|
223
211
|
${
|
|
@@ -235,6 +223,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
235
223
|
input = excluded.input,
|
|
236
224
|
output = excluded.output,
|
|
237
225
|
error = excluded.error,
|
|
226
|
+
awaiting = excluded.awaiting,
|
|
238
227
|
waiting_for = excluded.waiting_for,
|
|
239
228
|
pending_approval = excluded.pending_approval,
|
|
240
229
|
wake_at = excluded.wake_at,
|
|
@@ -402,6 +391,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
402
391
|
update ${tableSql.runs}
|
|
403
392
|
set
|
|
404
393
|
status = 'paused',
|
|
394
|
+
awaiting = ${encodeJsonOrNull(args.awaiting)}::jsonb,
|
|
405
395
|
waiting_for = ${encodeJsonOrNull(args.waitingFor)}::jsonb,
|
|
406
396
|
pending_approval = ${encodeJsonOrNull(args.pendingApproval)}::jsonb,
|
|
407
397
|
wake_at = ${args.wakeAt ?? null},
|
|
@@ -418,6 +408,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
418
408
|
set
|
|
419
409
|
status = 'finished',
|
|
420
410
|
output = ${encodeJson(args.output)}::jsonb,
|
|
411
|
+
awaiting = null,
|
|
421
412
|
waiting_for = null,
|
|
422
413
|
pending_approval = null,
|
|
423
414
|
wake_at = null,
|
|
@@ -435,6 +426,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
435
426
|
set
|
|
436
427
|
status = 'errored',
|
|
437
428
|
error = ${encodeJson(args.error)}::jsonb,
|
|
429
|
+
awaiting = null,
|
|
438
430
|
waiting_for = null,
|
|
439
431
|
pending_approval = null,
|
|
440
432
|
wake_at = null,
|
|
@@ -524,7 +516,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
524
516
|
)
|
|
525
517
|
if (existingDelivery) return { kind: 'duplicate', run }
|
|
526
518
|
|
|
527
|
-
if (run
|
|
519
|
+
if (!isRunWaitingForSignal(run, args.delivery)) {
|
|
528
520
|
return { kind: 'not-waiting', run }
|
|
529
521
|
}
|
|
530
522
|
|
|
@@ -549,6 +541,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
549
541
|
update ${tableSql.runs}
|
|
550
542
|
set
|
|
551
543
|
status = 'queued',
|
|
544
|
+
awaiting = null,
|
|
552
545
|
waiting_for = null,
|
|
553
546
|
pending_approval = null,
|
|
554
547
|
wake_at = null,
|
|
@@ -578,7 +571,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
578
571
|
)
|
|
579
572
|
if (existingDelivery) return { kind: 'duplicate', run }
|
|
580
573
|
|
|
581
|
-
if (run
|
|
574
|
+
if (!isRunWaitingForApproval(run, args.approval)) {
|
|
582
575
|
return { kind: 'not-waiting', run }
|
|
583
576
|
}
|
|
584
577
|
|
|
@@ -597,6 +590,7 @@ export function createDrizzlePostgresWorkflowStore(
|
|
|
597
590
|
update ${tableSql.runs}
|
|
598
591
|
set
|
|
599
592
|
status = 'queued',
|
|
593
|
+
awaiting = null,
|
|
600
594
|
waiting_for = null,
|
|
601
595
|
pending_approval = null,
|
|
602
596
|
wake_at = null,
|
|
@@ -824,6 +818,7 @@ interface RunRow {
|
|
|
824
818
|
input: unknown
|
|
825
819
|
output: unknown
|
|
826
820
|
error: unknown
|
|
821
|
+
awaiting: unknown
|
|
827
822
|
waiting_for: unknown
|
|
828
823
|
pending_approval: unknown
|
|
829
824
|
wake_at: number | string | null
|
|
@@ -841,6 +836,7 @@ interface RunStateRow {
|
|
|
841
836
|
input: unknown
|
|
842
837
|
output: unknown
|
|
843
838
|
error: unknown
|
|
839
|
+
awaiting: unknown
|
|
844
840
|
waiting_for: unknown
|
|
845
841
|
pending_approval: unknown
|
|
846
842
|
created_at: number | string
|
|
@@ -904,122 +900,6 @@ function tableSqls(
|
|
|
904
900
|
}
|
|
905
901
|
}
|
|
906
902
|
|
|
907
|
-
function schemaStatements(
|
|
908
|
-
schema: string | undefined,
|
|
909
|
-
tables: DrizzlePostgresWorkflowStoreTables,
|
|
910
|
-
): Array<string> {
|
|
911
|
-
const runs = qualifiedTableName(schema, tables.runs)
|
|
912
|
-
const runStates = qualifiedTableName(schema, tables.runStates)
|
|
913
|
-
const eventLocks = qualifiedTableName(schema, tables.eventLocks)
|
|
914
|
-
const events = qualifiedTableName(schema, tables.events)
|
|
915
|
-
const timers = qualifiedTableName(schema, tables.timers)
|
|
916
|
-
const signalDeliveries = qualifiedTableName(schema, tables.signalDeliveries)
|
|
917
|
-
const schedules = qualifiedTableName(schema, tables.schedules)
|
|
918
|
-
const scheduleBuckets = qualifiedTableName(schema, tables.scheduleBuckets)
|
|
919
|
-
|
|
920
|
-
return [
|
|
921
|
-
...(schema ? [`create schema if not exists ${quoteIdent(schema)}`] : []),
|
|
922
|
-
`create table if not exists ${runs} (
|
|
923
|
-
run_id text primary key,
|
|
924
|
-
workflow_id text not null,
|
|
925
|
-
workflow_version text,
|
|
926
|
-
status text not null,
|
|
927
|
-
input jsonb not null,
|
|
928
|
-
output jsonb,
|
|
929
|
-
error jsonb,
|
|
930
|
-
waiting_for jsonb,
|
|
931
|
-
pending_approval jsonb,
|
|
932
|
-
wake_at bigint,
|
|
933
|
-
lease_owner text,
|
|
934
|
-
lease_expires_at bigint,
|
|
935
|
-
created_at bigint not null,
|
|
936
|
-
updated_at bigint not null
|
|
937
|
-
)`,
|
|
938
|
-
`create index if not exists ${quoteIdent(`${tables.runs}_status_idx`)}
|
|
939
|
-
on ${runs} (status, updated_at)`,
|
|
940
|
-
`create index if not exists ${quoteIdent(`${tables.runs}_lease_idx`)}
|
|
941
|
-
on ${runs} (status, lease_expires_at)`,
|
|
942
|
-
`create table if not exists ${runStates} (
|
|
943
|
-
run_id text primary key,
|
|
944
|
-
workflow_id text not null,
|
|
945
|
-
workflow_version text,
|
|
946
|
-
status text not null,
|
|
947
|
-
input jsonb not null,
|
|
948
|
-
output jsonb,
|
|
949
|
-
error jsonb,
|
|
950
|
-
waiting_for jsonb,
|
|
951
|
-
pending_approval jsonb,
|
|
952
|
-
created_at bigint not null,
|
|
953
|
-
updated_at bigint not null
|
|
954
|
-
)`,
|
|
955
|
-
`create table if not exists ${eventLocks} (
|
|
956
|
-
run_id text primary key,
|
|
957
|
-
created_at bigint not null
|
|
958
|
-
)`,
|
|
959
|
-
`create table if not exists ${events} (
|
|
960
|
-
run_id text not null,
|
|
961
|
-
event_index integer not null,
|
|
962
|
-
event_type text not null,
|
|
963
|
-
step_id text,
|
|
964
|
-
event jsonb not null,
|
|
965
|
-
created_at bigint not null,
|
|
966
|
-
primary key (run_id, event_index)
|
|
967
|
-
)`,
|
|
968
|
-
`create index if not exists ${quoteIdent(`${tables.events}_type_idx`)}
|
|
969
|
-
on ${events} (run_id, event_type)`,
|
|
970
|
-
`create table if not exists ${timers} (
|
|
971
|
-
run_id text not null,
|
|
972
|
-
signal_id text not null,
|
|
973
|
-
workflow_id text not null,
|
|
974
|
-
workflow_version text,
|
|
975
|
-
wake_at bigint not null,
|
|
976
|
-
lease_owner text,
|
|
977
|
-
lease_expires_at bigint,
|
|
978
|
-
primary key (run_id, signal_id)
|
|
979
|
-
)`,
|
|
980
|
-
`create index if not exists ${quoteIdent(`${tables.timers}_due_idx`)}
|
|
981
|
-
on ${timers} (wake_at, lease_expires_at)`,
|
|
982
|
-
`create table if not exists ${signalDeliveries} (
|
|
983
|
-
run_id text not null,
|
|
984
|
-
signal_id text not null,
|
|
985
|
-
created_at bigint not null,
|
|
986
|
-
primary key (run_id, signal_id)
|
|
987
|
-
)`,
|
|
988
|
-
`create table if not exists ${schedules} (
|
|
989
|
-
schedule_id text primary key,
|
|
990
|
-
workflow_id text not null,
|
|
991
|
-
workflow_version text,
|
|
992
|
-
schedule jsonb not null,
|
|
993
|
-
overlap_policy text not null,
|
|
994
|
-
input jsonb,
|
|
995
|
-
next_fire_at bigint,
|
|
996
|
-
enabled boolean not null,
|
|
997
|
-
updated_at bigint not null
|
|
998
|
-
)`,
|
|
999
|
-
`create index if not exists ${quoteIdent(`${tables.schedules}_due_idx`)}
|
|
1000
|
-
on ${schedules} (enabled, next_fire_at)`,
|
|
1001
|
-
`create table if not exists ${scheduleBuckets} (
|
|
1002
|
-
schedule_id text not null,
|
|
1003
|
-
bucket_id text not null,
|
|
1004
|
-
workflow_id text not null,
|
|
1005
|
-
workflow_version text,
|
|
1006
|
-
run_id text not null,
|
|
1007
|
-
fire_at bigint not null,
|
|
1008
|
-
input jsonb,
|
|
1009
|
-
overlap_policy text not null,
|
|
1010
|
-
status text not null,
|
|
1011
|
-
lease_owner text,
|
|
1012
|
-
lease_expires_at bigint,
|
|
1013
|
-
started_at bigint,
|
|
1014
|
-
primary key (schedule_id, bucket_id)
|
|
1015
|
-
)`,
|
|
1016
|
-
`create index if not exists ${quoteIdent(
|
|
1017
|
-
`${tables.scheduleBuckets}_lease_idx`,
|
|
1018
|
-
)}
|
|
1019
|
-
on ${scheduleBuckets} (status, fire_at, lease_expires_at)`,
|
|
1020
|
-
]
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
903
|
async function loadRunById(
|
|
1024
904
|
db: DrizzlePostgresDatabase,
|
|
1025
905
|
tables: TableSqls,
|
|
@@ -1158,6 +1038,7 @@ function runFromRow(row: RunRow): WorkflowExecution {
|
|
|
1158
1038
|
input: decodeJson(row.input),
|
|
1159
1039
|
output: decodeJsonOrUndefined(row.output),
|
|
1160
1040
|
error: decodeJsonOrUndefined(row.error),
|
|
1041
|
+
awaiting: decodeJsonOrUndefined(row.awaiting),
|
|
1161
1042
|
waitingFor: decodeJsonOrUndefined(row.waiting_for),
|
|
1162
1043
|
pendingApproval: decodeJsonOrUndefined(row.pending_approval),
|
|
1163
1044
|
wakeAt: numberOrUndefined(row.wake_at),
|
|
@@ -1182,6 +1063,7 @@ function runStateFromRow(row: RunStateRow): RunState {
|
|
|
1182
1063
|
input: decodeJson(row.input),
|
|
1183
1064
|
output: decodeJsonOrUndefined(row.output),
|
|
1184
1065
|
error: decodeJsonOrUndefined(row.error),
|
|
1066
|
+
awaiting: decodeJsonOrUndefined(row.awaiting),
|
|
1185
1067
|
waitingFor: decodeJsonOrUndefined(row.waiting_for),
|
|
1186
1068
|
pendingApproval: decodeJsonOrUndefined(row.pending_approval),
|
|
1187
1069
|
createdAt: Number(row.created_at),
|
|
@@ -1210,6 +1092,54 @@ function timerFromRow(row: TimerRow): TimerWakeup {
|
|
|
1210
1092
|
}
|
|
1211
1093
|
}
|
|
1212
1094
|
|
|
1095
|
+
function isRunWaitingForSignal(
|
|
1096
|
+
run: WorkflowExecution,
|
|
1097
|
+
delivery: DeliverSignalArgs['delivery'],
|
|
1098
|
+
) {
|
|
1099
|
+
return (
|
|
1100
|
+
signalAwaitableMatches(run.waitingFor, delivery) ||
|
|
1101
|
+
run.awaiting?.some(
|
|
1102
|
+
(awaitable) =>
|
|
1103
|
+
awaitable.type === 'signal' &&
|
|
1104
|
+
signalAwaitableMatches(awaitable, delivery),
|
|
1105
|
+
) === true
|
|
1106
|
+
)
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
function signalAwaitableMatches(
|
|
1110
|
+
awaitable:
|
|
1111
|
+
| NonNullable<WorkflowExecution['waitingFor']>
|
|
1112
|
+
| Extract<
|
|
1113
|
+
NonNullable<WorkflowExecution['awaiting']>[number],
|
|
1114
|
+
{
|
|
1115
|
+
type: 'signal'
|
|
1116
|
+
}
|
|
1117
|
+
>
|
|
1118
|
+
| undefined,
|
|
1119
|
+
delivery: DeliverSignalArgs['delivery'],
|
|
1120
|
+
) {
|
|
1121
|
+
return (
|
|
1122
|
+
awaitable?.signalName === delivery.name &&
|
|
1123
|
+
(delivery.stepId === undefined ||
|
|
1124
|
+
awaitable.stepId === undefined ||
|
|
1125
|
+
awaitable.stepId === delivery.stepId)
|
|
1126
|
+
)
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
function isRunWaitingForApproval(
|
|
1130
|
+
run: WorkflowExecution,
|
|
1131
|
+
approval: DeliverApprovalArgs['approval'],
|
|
1132
|
+
) {
|
|
1133
|
+
return (
|
|
1134
|
+
run.pendingApproval?.approvalId === approval.approvalId ||
|
|
1135
|
+
run.awaiting?.some(
|
|
1136
|
+
(awaitable) =>
|
|
1137
|
+
awaitable.type === 'approval' &&
|
|
1138
|
+
awaitable.approvalId === approval.approvalId,
|
|
1139
|
+
) === true
|
|
1140
|
+
)
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1213
1143
|
function scheduleFromRow(row: ScheduleRow) {
|
|
1214
1144
|
return {
|
|
1215
1145
|
scheduleId: row.schedule_id satisfies ScheduleId,
|
|
@@ -1241,6 +1171,7 @@ function toRunSummary(row: RunRow): RunSummary {
|
|
|
1241
1171
|
workflowId: run.workflowId,
|
|
1242
1172
|
workflowVersion: run.workflowVersion,
|
|
1243
1173
|
status: run.status,
|
|
1174
|
+
awaiting: run.awaiting,
|
|
1244
1175
|
waitingFor: run.waitingFor,
|
|
1245
1176
|
pendingApproval: run.pendingApproval,
|
|
1246
1177
|
wakeAt: run.wakeAt,
|
|
@@ -1280,13 +1211,3 @@ function numberOrUndefined(value: number | string | null) {
|
|
|
1280
1211
|
function getStepId(event: WorkflowEvent) {
|
|
1281
1212
|
return 'stepId' in event ? event.stepId : undefined
|
|
1282
1213
|
}
|
|
1283
|
-
|
|
1284
|
-
function qualifiedTableName(schema: string | undefined, table: string) {
|
|
1285
|
-
return schema
|
|
1286
|
-
? `${quoteIdent(schema)}.${quoteIdent(table)}`
|
|
1287
|
-
: quoteIdent(table)
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
function quoteIdent(identifier: string) {
|
|
1291
|
-
return `"${identifier.replaceAll('"', '""')}"`
|
|
1292
|
-
}
|
package/src/tables.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
bigint,
|
|
3
|
+
boolean,
|
|
4
|
+
index,
|
|
5
|
+
integer,
|
|
6
|
+
jsonb,
|
|
7
|
+
pgTable,
|
|
8
|
+
primaryKey,
|
|
9
|
+
text,
|
|
10
|
+
} from 'drizzle-orm/pg-core'
|
|
11
|
+
|
|
12
|
+
export const workflowSchemaMigrations = pgTable('workflow_schema_migrations', {
|
|
13
|
+
migrationId: text('migration_id').primaryKey(),
|
|
14
|
+
packageName: text('package_name').notNull(),
|
|
15
|
+
packageVersion: text('package_version'),
|
|
16
|
+
appliedAt: bigint('applied_at', { mode: 'number' }).notNull(),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const workflowRuns = pgTable(
|
|
20
|
+
'workflow_runs',
|
|
21
|
+
{
|
|
22
|
+
runId: text('run_id').primaryKey(),
|
|
23
|
+
workflowId: text('workflow_id').notNull(),
|
|
24
|
+
workflowVersion: text('workflow_version'),
|
|
25
|
+
status: text('status').notNull(),
|
|
26
|
+
input: jsonb('input').notNull(),
|
|
27
|
+
output: jsonb('output'),
|
|
28
|
+
error: jsonb('error'),
|
|
29
|
+
awaiting: jsonb('awaiting'),
|
|
30
|
+
waitingFor: jsonb('waiting_for'),
|
|
31
|
+
pendingApproval: jsonb('pending_approval'),
|
|
32
|
+
wakeAt: bigint('wake_at', { mode: 'number' }),
|
|
33
|
+
leaseOwner: text('lease_owner'),
|
|
34
|
+
leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),
|
|
35
|
+
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
|
|
36
|
+
updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),
|
|
37
|
+
},
|
|
38
|
+
(table) => [
|
|
39
|
+
index('workflow_runs_status_idx').on(table.status, table.updatedAt),
|
|
40
|
+
index('workflow_runs_lease_idx').on(table.status, table.leaseExpiresAt),
|
|
41
|
+
],
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
export const workflowRunStates = pgTable('workflow_run_states', {
|
|
45
|
+
runId: text('run_id').primaryKey(),
|
|
46
|
+
workflowId: text('workflow_id').notNull(),
|
|
47
|
+
workflowVersion: text('workflow_version'),
|
|
48
|
+
status: text('status').notNull(),
|
|
49
|
+
input: jsonb('input').notNull(),
|
|
50
|
+
output: jsonb('output'),
|
|
51
|
+
error: jsonb('error'),
|
|
52
|
+
awaiting: jsonb('awaiting'),
|
|
53
|
+
waitingFor: jsonb('waiting_for'),
|
|
54
|
+
pendingApproval: jsonb('pending_approval'),
|
|
55
|
+
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
|
|
56
|
+
updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
export const workflowEventLocks = pgTable('workflow_event_locks', {
|
|
60
|
+
runId: text('run_id').primaryKey(),
|
|
61
|
+
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const workflowEvents = pgTable(
|
|
65
|
+
'workflow_events',
|
|
66
|
+
{
|
|
67
|
+
runId: text('run_id').notNull(),
|
|
68
|
+
eventIndex: integer('event_index').notNull(),
|
|
69
|
+
eventType: text('event_type').notNull(),
|
|
70
|
+
stepId: text('step_id'),
|
|
71
|
+
event: jsonb('event').notNull(),
|
|
72
|
+
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
|
|
73
|
+
},
|
|
74
|
+
(table) => [
|
|
75
|
+
primaryKey({ columns: [table.runId, table.eventIndex] }),
|
|
76
|
+
index('workflow_events_type_idx').on(table.runId, table.eventType),
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
export const workflowTimers = pgTable(
|
|
81
|
+
'workflow_timers',
|
|
82
|
+
{
|
|
83
|
+
runId: text('run_id').notNull(),
|
|
84
|
+
signalId: text('signal_id').notNull(),
|
|
85
|
+
workflowId: text('workflow_id').notNull(),
|
|
86
|
+
workflowVersion: text('workflow_version'),
|
|
87
|
+
wakeAt: bigint('wake_at', { mode: 'number' }).notNull(),
|
|
88
|
+
leaseOwner: text('lease_owner'),
|
|
89
|
+
leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),
|
|
90
|
+
},
|
|
91
|
+
(table) => [
|
|
92
|
+
primaryKey({ columns: [table.runId, table.signalId] }),
|
|
93
|
+
index('workflow_timers_due_idx').on(table.wakeAt, table.leaseExpiresAt),
|
|
94
|
+
],
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
export const workflowSignalDeliveries = pgTable(
|
|
98
|
+
'workflow_signal_deliveries',
|
|
99
|
+
{
|
|
100
|
+
runId: text('run_id').notNull(),
|
|
101
|
+
signalId: text('signal_id').notNull(),
|
|
102
|
+
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
|
|
103
|
+
},
|
|
104
|
+
(table) => [primaryKey({ columns: [table.runId, table.signalId] })],
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
export const workflowSchedules = pgTable(
|
|
108
|
+
'workflow_schedules',
|
|
109
|
+
{
|
|
110
|
+
scheduleId: text('schedule_id').primaryKey(),
|
|
111
|
+
workflowId: text('workflow_id').notNull(),
|
|
112
|
+
workflowVersion: text('workflow_version'),
|
|
113
|
+
schedule: jsonb('schedule').notNull(),
|
|
114
|
+
overlapPolicy: text('overlap_policy').notNull(),
|
|
115
|
+
input: jsonb('input'),
|
|
116
|
+
nextFireAt: bigint('next_fire_at', { mode: 'number' }),
|
|
117
|
+
enabled: boolean('enabled').notNull(),
|
|
118
|
+
updatedAt: bigint('updated_at', { mode: 'number' }).notNull(),
|
|
119
|
+
},
|
|
120
|
+
(table) => [
|
|
121
|
+
index('workflow_schedules_due_idx').on(table.enabled, table.nextFireAt),
|
|
122
|
+
],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
export const workflowScheduleBuckets = pgTable(
|
|
126
|
+
'workflow_schedule_buckets',
|
|
127
|
+
{
|
|
128
|
+
scheduleId: text('schedule_id').notNull(),
|
|
129
|
+
bucketId: text('bucket_id').notNull(),
|
|
130
|
+
workflowId: text('workflow_id').notNull(),
|
|
131
|
+
workflowVersion: text('workflow_version'),
|
|
132
|
+
runId: text('run_id').notNull(),
|
|
133
|
+
fireAt: bigint('fire_at', { mode: 'number' }).notNull(),
|
|
134
|
+
input: jsonb('input'),
|
|
135
|
+
overlapPolicy: text('overlap_policy').notNull(),
|
|
136
|
+
status: text('status').notNull(),
|
|
137
|
+
leaseOwner: text('lease_owner'),
|
|
138
|
+
leaseExpiresAt: bigint('lease_expires_at', { mode: 'number' }),
|
|
139
|
+
startedAt: bigint('started_at', { mode: 'number' }),
|
|
140
|
+
},
|
|
141
|
+
(table) => [
|
|
142
|
+
primaryKey({ columns: [table.scheduleId, table.bucketId] }),
|
|
143
|
+
index('workflow_schedule_buckets_lease_idx').on(
|
|
144
|
+
table.status,
|
|
145
|
+
table.fireAt,
|
|
146
|
+
table.leaseExpiresAt,
|
|
147
|
+
),
|
|
148
|
+
],
|
|
149
|
+
)
|