@dudousxd/nestjs-durable-store-drizzle 0.10.3 → 0.10.5
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.cjs +44 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -1
- package/dist/index.d.ts +54 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ var index_exports = {};
|
|
|
23
23
|
__export(index_exports, {
|
|
24
24
|
DrizzleStateStore: () => DrizzleStateStore,
|
|
25
25
|
bufferedSignals: () => bufferedSignals,
|
|
26
|
+
durableManagedTables: () => durableManagedTables,
|
|
26
27
|
durableSchema: () => durableSchema,
|
|
27
28
|
runAttributes: () => runAttributes,
|
|
28
29
|
signalWaiters: () => signalWaiters,
|
|
@@ -33,9 +34,10 @@ module.exports = __toCommonJS(index_exports);
|
|
|
33
34
|
|
|
34
35
|
// src/drizzle-state-store.ts
|
|
35
36
|
var import_nestjs_durable_core = require("@dudousxd/nestjs-durable-core");
|
|
36
|
-
var
|
|
37
|
+
var import_drizzle_orm2 = require("drizzle-orm");
|
|
37
38
|
|
|
38
39
|
// src/schema.ts
|
|
40
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
39
41
|
var import_sqlite_core = require("drizzle-orm/sqlite-core");
|
|
40
42
|
var workflowRuns = (0, import_sqlite_core.sqliteTable)("durable_workflow_runs", {
|
|
41
43
|
id: (0, import_sqlite_core.text)("id").primaryKey(),
|
|
@@ -54,6 +56,9 @@ var workflowRuns = (0, import_sqlite_core.sqliteTable)("durable_workflow_runs",
|
|
|
54
56
|
wakeAt: (0, import_sqlite_core.integer)("wake_at"),
|
|
55
57
|
lockedBy: (0, import_sqlite_core.text)("locked_by"),
|
|
56
58
|
lockedUntil: (0, import_sqlite_core.integer)("locked_until"),
|
|
59
|
+
// REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so
|
|
60
|
+
// only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.
|
|
61
|
+
awaitingDecisionTaskId: (0, import_sqlite_core.text)("awaiting_decision_task_id"),
|
|
57
62
|
recoveryAttempts: (0, import_sqlite_core.integer)("recovery_attempts"),
|
|
58
63
|
tags: (0, import_sqlite_core.text)("tags", {
|
|
59
64
|
mode: "json"
|
|
@@ -139,6 +144,10 @@ var durableSchema = {
|
|
|
139
144
|
signalWaiters,
|
|
140
145
|
bufferedSignals
|
|
141
146
|
};
|
|
147
|
+
function durableManagedTables() {
|
|
148
|
+
return Object.values(durableSchema).map((table) => (0, import_drizzle_orm.getTableName)(table));
|
|
149
|
+
}
|
|
150
|
+
__name(durableManagedTables, "durableManagedTables");
|
|
142
151
|
|
|
143
152
|
// src/drizzle-state-store.ts
|
|
144
153
|
var DrizzleStateStore = class {
|
|
@@ -155,28 +164,28 @@ var DrizzleStateStore = class {
|
|
|
155
164
|
}
|
|
156
165
|
async updateRun(runId, patch) {
|
|
157
166
|
const row = toRunPatch(patch);
|
|
158
|
-
if (Object.keys(row).length) await this.db.update(workflowRuns).set(row).where((0,
|
|
167
|
+
if (Object.keys(row).length) await this.db.update(workflowRuns).set(row).where((0, import_drizzle_orm2.eq)(workflowRuns.id, runId));
|
|
159
168
|
if ("searchAttributes" in patch) await this.reindexAttributes(runId, patch.searchAttributes);
|
|
160
169
|
}
|
|
161
170
|
/** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors
|
|
162
171
|
* the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */
|
|
163
172
|
async reindexAttributes(runId, attributes) {
|
|
164
|
-
await this.db.delete(runAttributes).where((0,
|
|
173
|
+
await this.db.delete(runAttributes).where((0, import_drizzle_orm2.eq)(runAttributes.runId, runId));
|
|
165
174
|
const rows = (0, import_nestjs_durable_core.normalizeAttributeRows)(runId, attributes);
|
|
166
175
|
if (rows.length) await this.db.insert(runAttributes).values(rows);
|
|
167
176
|
}
|
|
168
177
|
async getRun(runId) {
|
|
169
|
-
const rows = await this.db.select().from(workflowRuns).where((0,
|
|
178
|
+
const rows = await this.db.select().from(workflowRuns).where((0, import_drizzle_orm2.eq)(workflowRuns.id, runId)).limit(1);
|
|
170
179
|
return rows[0] ? fromRunRow(rows[0]) : null;
|
|
171
180
|
}
|
|
172
181
|
async deleteRun(runId) {
|
|
173
|
-
await this.db.delete(stepCheckpoints).where((0,
|
|
174
|
-
await this.db.delete(signalWaiters).where((0,
|
|
175
|
-
await this.db.delete(runAttributes).where((0,
|
|
176
|
-
await this.db.delete(workflowRuns).where((0,
|
|
182
|
+
await this.db.delete(stepCheckpoints).where((0, import_drizzle_orm2.eq)(stepCheckpoints.runId, runId));
|
|
183
|
+
await this.db.delete(signalWaiters).where((0, import_drizzle_orm2.eq)(signalWaiters.runId, runId));
|
|
184
|
+
await this.db.delete(runAttributes).where((0, import_drizzle_orm2.eq)(runAttributes.runId, runId));
|
|
185
|
+
await this.db.delete(workflowRuns).where((0, import_drizzle_orm2.eq)(workflowRuns.id, runId));
|
|
177
186
|
}
|
|
178
187
|
async getCheckpoint(runId, seq) {
|
|
179
|
-
const rows = await this.db.select().from(stepCheckpoints).where((0,
|
|
188
|
+
const rows = await this.db.select().from(stepCheckpoints).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(stepCheckpoints.runId, runId), (0, import_drizzle_orm2.eq)(stepCheckpoints.seq, seq))).limit(1);
|
|
180
189
|
return rows[0] ? fromCheckpointRow(rows[0]) : null;
|
|
181
190
|
}
|
|
182
191
|
async saveCheckpoint(checkpoint) {
|
|
@@ -205,53 +214,53 @@ var DrizzleStateStore = class {
|
|
|
205
214
|
}));
|
|
206
215
|
}
|
|
207
216
|
async listIncompleteRuns() {
|
|
208
|
-
const rows = await this.db.select().from(workflowRuns).where((0,
|
|
217
|
+
const rows = await this.db.select().from(workflowRuns).where((0, import_drizzle_orm2.inArray)(workflowRuns.status, [
|
|
209
218
|
"running",
|
|
210
219
|
"cancelling"
|
|
211
220
|
]));
|
|
212
221
|
return rows.map(fromRunRow);
|
|
213
222
|
}
|
|
214
223
|
async listPendingRuns(limit) {
|
|
215
|
-
const rows = await this.db.select().from(workflowRuns).where((0,
|
|
224
|
+
const rows = await this.db.select().from(workflowRuns).where((0, import_drizzle_orm2.eq)(workflowRuns.status, "pending")).orderBy((0, import_drizzle_orm2.asc)(workflowRuns.createdAt)).limit(limit);
|
|
216
225
|
return rows.map(fromRunRow);
|
|
217
226
|
}
|
|
218
227
|
async listDueTimers(nowMs) {
|
|
219
|
-
const rows = await this.db.select().from(workflowRuns).where((0,
|
|
228
|
+
const rows = await this.db.select().from(workflowRuns).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(workflowRuns.status, "suspended"), (0, import_drizzle_orm2.isNotNull)(workflowRuns.wakeAt), (0, import_drizzle_orm2.lte)(workflowRuns.wakeAt, nowMs)));
|
|
220
229
|
return rows.map(fromRunRow);
|
|
221
230
|
}
|
|
222
231
|
async tryLockRun(runId, owner, leaseUntilMs, nowMs) {
|
|
223
232
|
const result = await this.db.update(workflowRuns).set({
|
|
224
233
|
lockedBy: owner,
|
|
225
234
|
lockedUntil: leaseUntilMs
|
|
226
|
-
}).where((0,
|
|
235
|
+
}).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(workflowRuns.id, runId), (0, import_drizzle_orm2.or)((0, import_drizzle_orm2.isNull)(workflowRuns.lockedUntil), (0, import_drizzle_orm2.lte)(workflowRuns.lockedUntil, nowMs))));
|
|
227
236
|
return result.changes === 1;
|
|
228
237
|
}
|
|
229
238
|
async releaseRunLock(runId) {
|
|
230
239
|
await this.db.update(workflowRuns).set({
|
|
231
240
|
lockedBy: null,
|
|
232
241
|
lockedUntil: null
|
|
233
|
-
}).where((0,
|
|
242
|
+
}).where((0, import_drizzle_orm2.eq)(workflowRuns.id, runId));
|
|
234
243
|
}
|
|
235
244
|
async renewRunLock(runId, owner, leaseUntilMs) {
|
|
236
245
|
const result = await this.db.update(workflowRuns).set({
|
|
237
246
|
lockedUntil: leaseUntilMs
|
|
238
|
-
}).where((0,
|
|
247
|
+
}).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(workflowRuns.id, runId), (0, import_drizzle_orm2.eq)(workflowRuns.lockedBy, owner)));
|
|
239
248
|
return result.changes === 1;
|
|
240
249
|
}
|
|
241
250
|
async listRuns(query) {
|
|
242
251
|
const filters = [
|
|
243
|
-
query.workflow ? (0,
|
|
244
|
-
query.status ? (0,
|
|
252
|
+
query.workflow ? (0, import_drizzle_orm2.eq)(workflowRuns.workflow, query.workflow) : void 0,
|
|
253
|
+
query.status ? (0, import_drizzle_orm2.eq)(workflowRuns.status, query.status) : void 0,
|
|
245
254
|
// `status IN (...)`; an empty set matches nothing (mirrors the in-memory store).
|
|
246
|
-
query.statuses ? query.statuses.length ? (0,
|
|
255
|
+
query.statuses ? query.statuses.length ? (0, import_drizzle_orm2.inArray)(workflowRuns.status, query.statuses) : import_drizzle_orm2.sql`1 = 0` : void 0,
|
|
247
256
|
// `tags` is JSON text; match the quoted token so `etl` doesn't match `etl-foo`.
|
|
248
|
-
query.tag ? (0,
|
|
257
|
+
query.tag ? (0, import_drizzle_orm2.like)(workflowRuns.tags, `%"${query.tag}"%`) : void 0,
|
|
249
258
|
// Typed/range attribute predicates push DOWN into SQL: each filter becomes an EXISTS against
|
|
250
259
|
// the normalized `durable_run_attributes` side-table, so the DB filters AND paginates — no
|
|
251
260
|
// full scan + in-process filter. ANDed: a run must satisfy every filter (one EXISTS per filter).
|
|
252
261
|
...query.attributes?.map((f) => this.attributeExists(f)) ?? []
|
|
253
262
|
].filter((f) => f !== void 0);
|
|
254
|
-
const rows = await this.db.select().from(workflowRuns).where(filters.length ? (0,
|
|
263
|
+
const rows = await this.db.select().from(workflowRuns).where(filters.length ? (0, import_drizzle_orm2.and)(...filters) : void 0).orderBy((0, import_drizzle_orm2.desc)(workflowRuns.createdAt)).limit(query.limit ?? -1).offset(query.offset ?? 0);
|
|
255
264
|
return rows.map(fromRunRow);
|
|
256
265
|
}
|
|
257
266
|
/** One attribute predicate as an EXISTS subquery on the side-table, correlated to the outer run.
|
|
@@ -261,21 +270,21 @@ var DrizzleStateStore = class {
|
|
|
261
270
|
attributeExists(f) {
|
|
262
271
|
const col = (0, import_nestjs_durable_core.attributeColumnFor)(f) === "numValue" ? runAttributes.numValue : runAttributes.strValue;
|
|
263
272
|
const cmp = (0, import_nestjs_durable_core.sqlComparator)(f.op);
|
|
264
|
-
return (0,
|
|
265
|
-
one:
|
|
266
|
-
}).from(runAttributes).where((0,
|
|
273
|
+
return (0, import_drizzle_orm2.exists)(this.db.select({
|
|
274
|
+
one: import_drizzle_orm2.sql`1`
|
|
275
|
+
}).from(runAttributes).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(runAttributes.runId, workflowRuns.id), (0, import_drizzle_orm2.eq)(runAttributes.key, f.key), import_drizzle_orm2.sql`${col} ${import_drizzle_orm2.sql.raw(cmp)} ${(0, import_nestjs_durable_core.attributeOperand)(f)}`)));
|
|
267
276
|
}
|
|
268
277
|
async listCheckpoints(runId) {
|
|
269
|
-
const rows = await this.db.select().from(stepCheckpoints).where((0,
|
|
278
|
+
const rows = await this.db.select().from(stepCheckpoints).where((0, import_drizzle_orm2.eq)(stepCheckpoints.runId, runId)).orderBy((0, import_drizzle_orm2.asc)(stepCheckpoints.seq));
|
|
270
279
|
return rows.map(fromCheckpointRow);
|
|
271
280
|
}
|
|
272
281
|
async getLatestCheckpointByName(runId, name) {
|
|
273
|
-
const rows = await this.db.select().from(stepCheckpoints).where((0,
|
|
282
|
+
const rows = await this.db.select().from(stepCheckpoints).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(stepCheckpoints.runId, runId), (0, import_drizzle_orm2.eq)(stepCheckpoints.name, name))).orderBy((0, import_drizzle_orm2.desc)(stepCheckpoints.seq)).limit(1);
|
|
274
283
|
return rows[0] ? fromCheckpointRow(rows[0]) : void 0;
|
|
275
284
|
}
|
|
276
285
|
async listCheckpointsByNamePrefix(runId, prefixes) {
|
|
277
286
|
if (prefixes.length === 0) return [];
|
|
278
|
-
const rows = await this.db.select().from(stepCheckpoints).where((0,
|
|
287
|
+
const rows = await this.db.select().from(stepCheckpoints).where((0, import_drizzle_orm2.and)((0, import_drizzle_orm2.eq)(stepCheckpoints.runId, runId), (0, import_drizzle_orm2.or)(...prefixes.map((p) => (0, import_drizzle_orm2.like)(stepCheckpoints.name, `${p}%`))))).orderBy((0, import_drizzle_orm2.asc)(stepCheckpoints.seq));
|
|
279
288
|
return rows.map(fromCheckpointRow);
|
|
280
289
|
}
|
|
281
290
|
async putSignalWaiter(waiter) {
|
|
@@ -294,10 +303,10 @@ var DrizzleStateStore = class {
|
|
|
294
303
|
});
|
|
295
304
|
}
|
|
296
305
|
async takeSignalWaiter(token) {
|
|
297
|
-
const rows = await this.db.select().from(signalWaiters).where((0,
|
|
306
|
+
const rows = await this.db.select().from(signalWaiters).where((0, import_drizzle_orm2.eq)(signalWaiters.token, token)).limit(1);
|
|
298
307
|
const row = rows[0];
|
|
299
308
|
if (!row) return null;
|
|
300
|
-
await this.db.delete(signalWaiters).where((0,
|
|
309
|
+
await this.db.delete(signalWaiters).where((0, import_drizzle_orm2.eq)(signalWaiters.token, token));
|
|
301
310
|
return {
|
|
302
311
|
token: row.token,
|
|
303
312
|
runId: row.runId,
|
|
@@ -306,7 +315,7 @@ var DrizzleStateStore = class {
|
|
|
306
315
|
};
|
|
307
316
|
}
|
|
308
317
|
async listSignalWaiters(prefix) {
|
|
309
|
-
const rows = await this.db.select().from(signalWaiters).where((0,
|
|
318
|
+
const rows = await this.db.select().from(signalWaiters).where((0, import_drizzle_orm2.like)(signalWaiters.token, `${prefix}%`));
|
|
310
319
|
return rows.map((r) => ({
|
|
311
320
|
token: r.token,
|
|
312
321
|
runId: r.runId,
|
|
@@ -321,10 +330,10 @@ var DrizzleStateStore = class {
|
|
|
321
330
|
});
|
|
322
331
|
}
|
|
323
332
|
async takeBufferedSignal(token) {
|
|
324
|
-
const rows = await this.db.select().from(bufferedSignals).where((0,
|
|
333
|
+
const rows = await this.db.select().from(bufferedSignals).where((0, import_drizzle_orm2.eq)(bufferedSignals.token, token)).orderBy((0, import_drizzle_orm2.asc)(bufferedSignals.id)).limit(1);
|
|
325
334
|
const row = rows[0];
|
|
326
335
|
if (!row) return null;
|
|
327
|
-
await this.db.delete(bufferedSignals).where((0,
|
|
336
|
+
await this.db.delete(bufferedSignals).where((0, import_drizzle_orm2.eq)(bufferedSignals.id, row.id));
|
|
328
337
|
return {
|
|
329
338
|
payload: row.payload ?? void 0
|
|
330
339
|
};
|
|
@@ -342,6 +351,7 @@ function toRunRow(run) {
|
|
|
342
351
|
wakeAt: run.wakeAt ?? null,
|
|
343
352
|
lockedBy: run.lockedBy ?? null,
|
|
344
353
|
lockedUntil: run.lockedUntil ?? null,
|
|
354
|
+
awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,
|
|
345
355
|
recoveryAttempts: run.recoveryAttempts ?? null,
|
|
346
356
|
tags: run.tags ?? null,
|
|
347
357
|
searchAttributes: run.searchAttributes ?? null,
|
|
@@ -362,6 +372,7 @@ function toRunPatch(patch) {
|
|
|
362
372
|
if ("wakeAt" in patch) row.wakeAt = patch.wakeAt ?? null;
|
|
363
373
|
if ("lockedBy" in patch) row.lockedBy = patch.lockedBy ?? null;
|
|
364
374
|
if ("lockedUntil" in patch) row.lockedUntil = patch.lockedUntil ?? null;
|
|
375
|
+
if ("awaitingDecisionTaskId" in patch) row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;
|
|
365
376
|
if ("recoveryAttempts" in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;
|
|
366
377
|
if ("tags" in patch) row.tags = patch.tags ?? null;
|
|
367
378
|
if ("searchAttributes" in patch) row.searchAttributes = patch.searchAttributes ?? null;
|
|
@@ -383,6 +394,7 @@ function fromRunRow(row) {
|
|
|
383
394
|
wakeAt: row.wakeAt ?? void 0,
|
|
384
395
|
lockedBy: row.lockedBy ?? void 0,
|
|
385
396
|
lockedUntil: row.lockedUntil ?? void 0,
|
|
397
|
+
awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? void 0,
|
|
386
398
|
recoveryAttempts: row.recoveryAttempts ?? void 0,
|
|
387
399
|
tags: row.tags ?? void 0,
|
|
388
400
|
searchAttributes: row.searchAttributes ?? void 0,
|
|
@@ -440,6 +452,7 @@ __name(fromCheckpointRow, "fromCheckpointRow");
|
|
|
440
452
|
0 && (module.exports = {
|
|
441
453
|
DrizzleStateStore,
|
|
442
454
|
bufferedSignals,
|
|
455
|
+
durableManagedTables,
|
|
443
456
|
durableSchema,
|
|
444
457
|
runAttributes,
|
|
445
458
|
signalWaiters,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/drizzle-state-store.ts","../src/schema.ts"],"sourcesContent":["export * from './drizzle-state-store';\nexport * from './schema';\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n inArray,\n isNotNull,\n isNull,\n like,\n lte,\n or,\n sql,\n} from 'drizzle-orm';\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';\nimport {\n bufferedSignals,\n runAttributes,\n signalWaiters,\n stepCheckpoints,\n workflowRuns,\n} from './schema';\n\ntype RunRow = typeof workflowRuns.$inferSelect;\ntype CheckpointRow = typeof stepCheckpoints.$inferSelect;\ntype DrizzleSqlite = BaseSQLiteDatabase<'sync' | 'async', unknown>;\n\n/**\n * Drizzle (SQLite / libSQL) `StateStore`. Pass a drizzle db built with `./schema`. Timestamps are\n * epoch-ms integers (SQLite's 64-bit integers hold them fine). For Postgres or MySQL, use the\n * MikroORM, TypeORM or Prisma adapter.\n */\nexport class DrizzleStateStore implements StateStore {\n constructor(private readonly db: DrizzleSqlite) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.insert(workflowRuns).values(toRunRow(run));\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const row = toRunPatch(patch);\n // Drizzle throws on `.set({})`; skip the UPDATE when no mapped column actually changed.\n if (Object.keys(row).length)\n await this.db.update(workflowRuns).set(row).where(eq(workflowRuns.id, runId));\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n ): Promise<void> {\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.insert(runAttributes).values(rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.id, runId))\n .limit(1);\n return rows[0] ? fromRunRow(rows[0]) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.delete(stepCheckpoints).where(eq(stepCheckpoints.runId, runId));\n await this.db.delete(signalWaiters).where(eq(signalWaiters.runId, runId));\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n await this.db.delete(workflowRuns).where(eq(workflowRuns.id, runId));\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.seq, seq)))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const row = toCheckpointRow(checkpoint);\n await this.db\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({ target: [stepCheckpoints.runId, stepCheckpoints.seq], set: row });\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.db.transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const row = toCheckpointRow(cp);\n await tx\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({\n target: [stepCheckpoints.runId, stepCheckpoints.seq],\n set: row,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(inArray(workflowRuns.status, ['running', 'cancelling']));\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.status, 'pending'))\n .orderBy(asc(workflowRuns.createdAt)) // FIFO dispatch\n .limit(limit);\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(\n and(\n eq(workflowRuns.status, 'suspended'),\n isNotNull(workflowRuns.wakeAt),\n lte(workflowRuns.wakeAt, nowMs),\n ),\n );\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedBy: owner, lockedUntil: leaseUntilMs })\n .where(\n and(\n eq(workflowRuns.id, runId),\n or(isNull(workflowRuns.lockedUntil), lte(workflowRuns.lockedUntil, nowMs)),\n ),\n );\n return (result as { changes?: number }).changes === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db\n .update(workflowRuns)\n .set({ lockedBy: null, lockedUntil: null })\n .where(eq(workflowRuns.id, runId));\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedUntil: leaseUntilMs })\n .where(and(eq(workflowRuns.id, runId), eq(workflowRuns.lockedBy, owner)));\n return (result as { changes?: number }).changes === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const filters = [\n query.workflow ? eq(workflowRuns.workflow, query.workflow) : undefined,\n query.status ? eq(workflowRuns.status, query.status) : undefined,\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store).\n query.statuses\n ? query.statuses.length\n ? inArray(workflowRuns.status, query.statuses)\n : sql`1 = 0`\n : undefined,\n // `tags` is JSON text; match the quoted token so `etl` doesn't match `etl-foo`.\n query.tag ? like(workflowRuns.tags, `%\"${query.tag}\"%`) : undefined,\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes an EXISTS against\n // the normalized `durable_run_attributes` side-table, so the DB filters AND paginates — no\n // full scan + in-process filter. ANDed: a run must satisfy every filter (one EXISTS per filter).\n ...(query.attributes?.map((f) => this.attributeExists(f)) ?? []),\n ].filter((f): f is NonNullable<typeof f> => f !== undefined);\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(filters.length ? and(...filters) : undefined)\n .orderBy(desc(workflowRuns.createdAt)) // newest first — recent runs on top in the dashboard\n .limit(query.limit ?? -1)\n .offset(query.offset ?? 0);\n return rows.map(fromRunRow);\n }\n\n /** One attribute predicate as an EXISTS subquery on the side-table, correlated to the outer run.\n * `<>` (ne) also excludes runs where the attribute is absent (the missing-key-never-matches\n * contract): EXISTS already requires the key row to be present, so EXISTS(... <> ...) is exactly\n * ne-with-present. Numeric operands compare `num_value`, everything else `str_value`. */\n private attributeExists(f: AttributeFilter) {\n const col =\n attributeColumnFor(f) === 'numValue' ? runAttributes.numValue : runAttributes.strValue;\n const cmp = sqlComparator(f.op);\n return exists(\n this.db\n .select({ one: sql`1` })\n .from(runAttributes)\n .where(\n and(\n eq(runAttributes.runId, workflowRuns.id),\n eq(runAttributes.key, f.key),\n sql`${col} ${sql.raw(cmp)} ${attributeOperand(f)}`,\n ),\n ),\n );\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(eq(stepCheckpoints.runId, runId))\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.name, name)))\n .orderBy(desc(stepCheckpoints.seq))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(\n and(\n eq(stepCheckpoints.runId, runId),\n or(...prefixes.map((p) => like(stepCheckpoints.name, `${p}%`))),\n ),\n )\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db\n .insert(signalWaiters)\n .values({\n token: waiter.token,\n runId: waiter.runId,\n seq: waiter.seq,\n parallelGroup: waiter.parallelGroup ?? null,\n })\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq, parallelGroup: waiter.parallelGroup ?? null },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(eq(signalWaiters.token, token))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(signalWaiters).where(eq(signalWaiters.token, token));\n return {\n token: row.token,\n runId: row.runId,\n seq: row.seq,\n parallelGroup: row.parallelGroup ?? undefined,\n };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(like(signalWaiters.token, `${prefix}%`));\n return rows.map((r) => ({\n token: r.token,\n runId: r.runId,\n seq: r.seq,\n parallelGroup: r.parallelGroup ?? undefined,\n }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.insert(bufferedSignals).values({ token, payload: payload ?? null });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const rows = await this.db\n .select()\n .from(bufferedSignals)\n .where(eq(bufferedSignals.token, token))\n .orderBy(asc(bufferedSignals.id))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(bufferedSignals).where(eq(bufferedSignals.id, row.id));\n return { payload: row.payload ?? undefined };\n }\n}\n\nfunction toRunRow(run: WorkflowRun): RunRow {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: run.input ?? null,\n output: run.output ?? null,\n error: run.error ?? null,\n wakeAt: run.wakeAt ?? null,\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil ?? null,\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: run.tags ?? null,\n searchAttributes: run.searchAttributes ?? null,\n priority: run.priority ?? null,\n createdAt: run.createdAt.getTime(),\n updatedAt: run.updatedAt.getTime(),\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>): Partial<RunRow> {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const row: Partial<RunRow> = {};\n if ('workflow' in patch) row.workflow = patch.workflow;\n if ('workflowVersion' in patch) row.workflowVersion = patch.workflowVersion;\n if ('status' in patch) row.status = patch.status;\n if ('input' in patch) row.input = patch.input ?? null;\n if ('output' in patch) row.output = patch.output ?? null;\n if ('error' in patch) row.error = patch.error ?? null;\n if ('wakeAt' in patch) row.wakeAt = patch.wakeAt ?? null;\n if ('lockedBy' in patch) row.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch) row.lockedUntil = patch.lockedUntil ?? null;\n if ('recoveryAttempts' in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) row.tags = patch.tags ?? null;\n if ('searchAttributes' in patch) row.searchAttributes = patch.searchAttributes ?? null;\n if ('priority' in patch) row.priority = patch.priority ?? null;\n if (patch.createdAt != null) row.createdAt = patch.createdAt.getTime();\n if (patch.updatedAt != null) row.updatedAt = patch.updatedAt.getTime();\n return row;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: row.wakeAt ?? undefined,\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil ?? undefined,\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: row.tags ?? undefined,\n searchAttributes: row.searchAttributes ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: new Date(row.createdAt),\n updatedAt: new Date(row.updatedAt),\n };\n}\n\nfunction toCheckpointRow(cp: StepCheckpoint): CheckpointRow {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: cp.input ?? null,\n output: cp.output ?? null,\n error: cp.error ?? null,\n events: cp.events ?? null,\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n parallelGroup: cp.parallelGroup ?? null,\n wakeAt: cp.wakeAt ?? null,\n enqueuedAt: (cp.enqueuedAt ?? cp.startedAt).getTime(),\n startedAt: cp.startedAt.getTime(),\n finishedAt: cp.finishedAt.getTime(),\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n parallelGroup: row.parallelGroup ?? undefined,\n wakeAt: row.wakeAt ?? undefined,\n enqueuedAt: row.enqueuedAt == null ? new Date(row.startedAt) : new Date(row.enqueuedAt),\n startedAt: new Date(row.startedAt),\n finishedAt: new Date(row.finishedAt),\n };\n}\n","import { integer, primaryKey, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';\n\n// SQLite / libSQL schema for the durable tables. Timestamps and `wakeAt` are epoch-ms integers\n// (SQLite has no native date type). Import these tables and pass them with your drizzle db.\n\nexport const workflowRuns = sqliteTable('durable_workflow_runs', {\n id: text('id').primaryKey(),\n workflow: text('workflow').notNull(),\n workflowVersion: text('workflow_version').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n wakeAt: integer('wake_at'),\n lockedBy: text('locked_by'),\n lockedUntil: integer('locked_until'),\n recoveryAttempts: integer('recovery_attempts'),\n tags: text('tags', { mode: 'json' }).$type<string[]>(),\n searchAttributes: text('search_attributes', { mode: 'json' }).$type<\n Record<string, string | number | boolean>\n >(),\n priority: integer('priority'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n\nexport const stepCheckpoints = sqliteTable(\n 'durable_step_checkpoints',\n {\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n name: text('name').notNull(),\n kind: text('kind').notNull(),\n stepId: text('step_id').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n events: text('events', { mode: 'json' }),\n attempts: integer('attempts').notNull(),\n workerGroup: text('worker_group'),\n // A ctx.gather/ctx.all fan tags every sibling step with the same group so the dashboard renders\n // them as one parallel group; the core engine sets it (incl. from a remote worker's recordStep).\n parallelGroup: text('parallel_group'),\n wakeAt: integer('wake_at'),\n enqueuedAt: integer('enqueued_at'),\n startedAt: integer('started_at').notNull(),\n finishedAt: integer('finished_at').notNull(),\n },\n (t) => [primaryKey({ columns: [t.runId, t.seq] })],\n);\n\n// Normalized search-attribute side-table: one row per (run, key), so range/equality attribute\n// predicates push DOWN into SQL via an EXISTS join instead of a coarse scan + in-process filter.\n// Maintained on every createRun/updateRun. Numbers land in `numValue`, strings/booleans in\n// `strValue` (booleans as \"true\"/\"false\"); see core `normalizeAttributeRows`.\nexport const runAttributes = sqliteTable(\n 'durable_run_attributes',\n {\n runId: text('run_id').notNull(),\n key: text('key').notNull(),\n strValue: text('str_value'),\n numValue: real('num_value'),\n },\n (t) => [primaryKey({ columns: [t.runId, t.key] })],\n);\n\nexport const signalWaiters = sqliteTable('durable_signal_waiters', {\n token: text('token').primaryKey(),\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n // A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the\n // engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the\n // dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.\n parallelGroup: text('parallel_group'),\n});\n\nexport const bufferedSignals = sqliteTable('durable_buffered_signals', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n token: text('token').notNull(),\n payload: text('payload', { mode: 'json' }),\n});\n\nexport const durableSchema = {\n workflowRuns,\n stepCheckpoints,\n runAttributes,\n signalWaiters,\n bufferedSignals,\n};\n"],"mappings":"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","names":["workflowRuns","sqliteTable","id","text","primaryKey","workflow","notNull","workflowVersion","status","input","mode","output","error","wakeAt","integer","lockedBy","lockedUntil","recoveryAttempts","tags","$type","searchAttributes","priority","createdAt","updatedAt","stepCheckpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","parallelGroup","enqueuedAt","startedAt","finishedAt","t","columns","runAttributes","key","strValue","numValue","real","signalWaiters","token","bufferedSignals","autoIncrement","payload","durableSchema","DrizzleStateStore","db","createRun","run","insert","workflowRuns","values","toRunRow","reindexAttributes","id","searchAttributes","updateRun","runId","patch","row","toRunPatch","Object","keys","length","update","set","where","eq","attributes","delete","runAttributes","rows","normalizeAttributeRows","getRun","select","from","limit","fromRunRow","deleteRun","stepCheckpoints","signalWaiters","getCheckpoint","seq","and","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointRow","onConflictDoUpdate","target","transaction","work","tx","raw","cp","listIncompleteRuns","inArray","status","map","listPendingRuns","orderBy","asc","createdAt","listDueTimers","nowMs","isNotNull","wakeAt","lte","tryLockRun","owner","leaseUntilMs","result","lockedBy","lockedUntil","or","isNull","changes","releaseRunLock","renewRunLock","listRuns","query","filters","workflow","undefined","statuses","sql","tag","like","tags","f","attributeExists","filter","desc","offset","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","exists","one","key","attributeOperand","listCheckpoints","getLatestCheckpointByName","name","listCheckpointsByNamePrefix","prefixes","p","putSignalWaiter","waiter","token","parallelGroup","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/drizzle-state-store.ts","../src/schema.ts"],"sourcesContent":["export * from './drizzle-state-store';\nexport * from './schema';\n","import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n inArray,\n isNotNull,\n isNull,\n like,\n lte,\n or,\n sql,\n} from 'drizzle-orm';\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';\nimport {\n bufferedSignals,\n runAttributes,\n signalWaiters,\n stepCheckpoints,\n workflowRuns,\n} from './schema';\n\ntype RunRow = typeof workflowRuns.$inferSelect;\ntype CheckpointRow = typeof stepCheckpoints.$inferSelect;\ntype DrizzleSqlite = BaseSQLiteDatabase<'sync' | 'async', unknown>;\n\n/**\n * Drizzle (SQLite / libSQL) `StateStore`. Pass a drizzle db built with `./schema`. Timestamps are\n * epoch-ms integers (SQLite's 64-bit integers hold them fine). For Postgres or MySQL, use the\n * MikroORM, TypeORM or Prisma adapter.\n */\nexport class DrizzleStateStore implements StateStore {\n constructor(private readonly db: DrizzleSqlite) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.insert(workflowRuns).values(toRunRow(run));\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const row = toRunPatch(patch);\n // Drizzle throws on `.set({})`; skip the UPDATE when no mapped column actually changed.\n if (Object.keys(row).length)\n await this.db.update(workflowRuns).set(row).where(eq(workflowRuns.id, runId));\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n ): Promise<void> {\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.insert(runAttributes).values(rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.id, runId))\n .limit(1);\n return rows[0] ? fromRunRow(rows[0]) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.delete(stepCheckpoints).where(eq(stepCheckpoints.runId, runId));\n await this.db.delete(signalWaiters).where(eq(signalWaiters.runId, runId));\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n await this.db.delete(workflowRuns).where(eq(workflowRuns.id, runId));\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.seq, seq)))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const row = toCheckpointRow(checkpoint);\n await this.db\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({ target: [stepCheckpoints.runId, stepCheckpoints.seq], set: row });\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.db.transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const row = toCheckpointRow(cp);\n await tx\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({\n target: [stepCheckpoints.runId, stepCheckpoints.seq],\n set: row,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(inArray(workflowRuns.status, ['running', 'cancelling']));\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.status, 'pending'))\n .orderBy(asc(workflowRuns.createdAt)) // FIFO dispatch\n .limit(limit);\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(\n and(\n eq(workflowRuns.status, 'suspended'),\n isNotNull(workflowRuns.wakeAt),\n lte(workflowRuns.wakeAt, nowMs),\n ),\n );\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedBy: owner, lockedUntil: leaseUntilMs })\n .where(\n and(\n eq(workflowRuns.id, runId),\n or(isNull(workflowRuns.lockedUntil), lte(workflowRuns.lockedUntil, nowMs)),\n ),\n );\n return (result as { changes?: number }).changes === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db\n .update(workflowRuns)\n .set({ lockedBy: null, lockedUntil: null })\n .where(eq(workflowRuns.id, runId));\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedUntil: leaseUntilMs })\n .where(and(eq(workflowRuns.id, runId), eq(workflowRuns.lockedBy, owner)));\n return (result as { changes?: number }).changes === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const filters = [\n query.workflow ? eq(workflowRuns.workflow, query.workflow) : undefined,\n query.status ? eq(workflowRuns.status, query.status) : undefined,\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store).\n query.statuses\n ? query.statuses.length\n ? inArray(workflowRuns.status, query.statuses)\n : sql`1 = 0`\n : undefined,\n // `tags` is JSON text; match the quoted token so `etl` doesn't match `etl-foo`.\n query.tag ? like(workflowRuns.tags, `%\"${query.tag}\"%`) : undefined,\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes an EXISTS against\n // the normalized `durable_run_attributes` side-table, so the DB filters AND paginates — no\n // full scan + in-process filter. ANDed: a run must satisfy every filter (one EXISTS per filter).\n ...(query.attributes?.map((f) => this.attributeExists(f)) ?? []),\n ].filter((f): f is NonNullable<typeof f> => f !== undefined);\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(filters.length ? and(...filters) : undefined)\n .orderBy(desc(workflowRuns.createdAt)) // newest first — recent runs on top in the dashboard\n .limit(query.limit ?? -1)\n .offset(query.offset ?? 0);\n return rows.map(fromRunRow);\n }\n\n /** One attribute predicate as an EXISTS subquery on the side-table, correlated to the outer run.\n * `<>` (ne) also excludes runs where the attribute is absent (the missing-key-never-matches\n * contract): EXISTS already requires the key row to be present, so EXISTS(... <> ...) is exactly\n * ne-with-present. Numeric operands compare `num_value`, everything else `str_value`. */\n private attributeExists(f: AttributeFilter) {\n const col =\n attributeColumnFor(f) === 'numValue' ? runAttributes.numValue : runAttributes.strValue;\n const cmp = sqlComparator(f.op);\n return exists(\n this.db\n .select({ one: sql`1` })\n .from(runAttributes)\n .where(\n and(\n eq(runAttributes.runId, workflowRuns.id),\n eq(runAttributes.key, f.key),\n sql`${col} ${sql.raw(cmp)} ${attributeOperand(f)}`,\n ),\n ),\n );\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(eq(stepCheckpoints.runId, runId))\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.name, name)))\n .orderBy(desc(stepCheckpoints.seq))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(\n and(\n eq(stepCheckpoints.runId, runId),\n or(...prefixes.map((p) => like(stepCheckpoints.name, `${p}%`))),\n ),\n )\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db\n .insert(signalWaiters)\n .values({\n token: waiter.token,\n runId: waiter.runId,\n seq: waiter.seq,\n parallelGroup: waiter.parallelGroup ?? null,\n })\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq, parallelGroup: waiter.parallelGroup ?? null },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(eq(signalWaiters.token, token))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(signalWaiters).where(eq(signalWaiters.token, token));\n return {\n token: row.token,\n runId: row.runId,\n seq: row.seq,\n parallelGroup: row.parallelGroup ?? undefined,\n };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(like(signalWaiters.token, `${prefix}%`));\n return rows.map((r) => ({\n token: r.token,\n runId: r.runId,\n seq: r.seq,\n parallelGroup: r.parallelGroup ?? undefined,\n }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.insert(bufferedSignals).values({ token, payload: payload ?? null });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const rows = await this.db\n .select()\n .from(bufferedSignals)\n .where(eq(bufferedSignals.token, token))\n .orderBy(asc(bufferedSignals.id))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(bufferedSignals).where(eq(bufferedSignals.id, row.id));\n return { payload: row.payload ?? undefined };\n }\n}\n\nfunction toRunRow(run: WorkflowRun): RunRow {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: run.input ?? null,\n output: run.output ?? null,\n error: run.error ?? null,\n wakeAt: run.wakeAt ?? null,\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil ?? null,\n awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: run.tags ?? null,\n searchAttributes: run.searchAttributes ?? null,\n priority: run.priority ?? null,\n createdAt: run.createdAt.getTime(),\n updatedAt: run.updatedAt.getTime(),\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>): Partial<RunRow> {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const row: Partial<RunRow> = {};\n if ('workflow' in patch) row.workflow = patch.workflow;\n if ('workflowVersion' in patch) row.workflowVersion = patch.workflowVersion;\n if ('status' in patch) row.status = patch.status;\n if ('input' in patch) row.input = patch.input ?? null;\n if ('output' in patch) row.output = patch.output ?? null;\n if ('error' in patch) row.error = patch.error ?? null;\n if ('wakeAt' in patch) row.wakeAt = patch.wakeAt ?? null;\n if ('lockedBy' in patch) row.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch) row.lockedUntil = patch.lockedUntil ?? null;\n if ('awaitingDecisionTaskId' in patch)\n row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;\n if ('recoveryAttempts' in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) row.tags = patch.tags ?? null;\n if ('searchAttributes' in patch) row.searchAttributes = patch.searchAttributes ?? null;\n if ('priority' in patch) row.priority = patch.priority ?? null;\n if (patch.createdAt != null) row.createdAt = patch.createdAt.getTime();\n if (patch.updatedAt != null) row.updatedAt = patch.updatedAt.getTime();\n return row;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: row.wakeAt ?? undefined,\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil ?? undefined,\n awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? undefined,\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: row.tags ?? undefined,\n searchAttributes: row.searchAttributes ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: new Date(row.createdAt),\n updatedAt: new Date(row.updatedAt),\n };\n}\n\nfunction toCheckpointRow(cp: StepCheckpoint): CheckpointRow {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: cp.input ?? null,\n output: cp.output ?? null,\n error: cp.error ?? null,\n events: cp.events ?? null,\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n parallelGroup: cp.parallelGroup ?? null,\n wakeAt: cp.wakeAt ?? null,\n enqueuedAt: (cp.enqueuedAt ?? cp.startedAt).getTime(),\n startedAt: cp.startedAt.getTime(),\n finishedAt: cp.finishedAt.getTime(),\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n parallelGroup: row.parallelGroup ?? undefined,\n wakeAt: row.wakeAt ?? undefined,\n enqueuedAt: row.enqueuedAt == null ? new Date(row.startedAt) : new Date(row.enqueuedAt),\n startedAt: new Date(row.startedAt),\n finishedAt: new Date(row.finishedAt),\n };\n}\n","import { getTableName } from 'drizzle-orm';\nimport { integer, primaryKey, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';\n\n// SQLite / libSQL schema for the durable tables. Timestamps and `wakeAt` are epoch-ms integers\n// (SQLite has no native date type). Import these tables and pass them with your drizzle db.\n\nexport const workflowRuns = sqliteTable('durable_workflow_runs', {\n id: text('id').primaryKey(),\n workflow: text('workflow').notNull(),\n workflowVersion: text('workflow_version').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n wakeAt: integer('wake_at'),\n lockedBy: text('locked_by'),\n lockedUntil: integer('locked_until'),\n // REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so\n // only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.\n awaitingDecisionTaskId: text('awaiting_decision_task_id'),\n recoveryAttempts: integer('recovery_attempts'),\n tags: text('tags', { mode: 'json' }).$type<string[]>(),\n searchAttributes: text('search_attributes', { mode: 'json' }).$type<\n Record<string, string | number | boolean>\n >(),\n priority: integer('priority'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n\nexport const stepCheckpoints = sqliteTable(\n 'durable_step_checkpoints',\n {\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n name: text('name').notNull(),\n kind: text('kind').notNull(),\n stepId: text('step_id').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n events: text('events', { mode: 'json' }),\n attempts: integer('attempts').notNull(),\n workerGroup: text('worker_group'),\n // A ctx.gather/ctx.all fan tags every sibling step with the same group so the dashboard renders\n // them as one parallel group; the core engine sets it (incl. from a remote worker's recordStep).\n parallelGroup: text('parallel_group'),\n wakeAt: integer('wake_at'),\n enqueuedAt: integer('enqueued_at'),\n startedAt: integer('started_at').notNull(),\n finishedAt: integer('finished_at').notNull(),\n },\n (t) => [primaryKey({ columns: [t.runId, t.seq] })],\n);\n\n// Normalized search-attribute side-table: one row per (run, key), so range/equality attribute\n// predicates push DOWN into SQL via an EXISTS join instead of a coarse scan + in-process filter.\n// Maintained on every createRun/updateRun. Numbers land in `numValue`, strings/booleans in\n// `strValue` (booleans as \"true\"/\"false\"); see core `normalizeAttributeRows`.\nexport const runAttributes = sqliteTable(\n 'durable_run_attributes',\n {\n runId: text('run_id').notNull(),\n key: text('key').notNull(),\n strValue: text('str_value'),\n numValue: real('num_value'),\n },\n (t) => [primaryKey({ columns: [t.runId, t.key] })],\n);\n\nexport const signalWaiters = sqliteTable('durable_signal_waiters', {\n token: text('token').primaryKey(),\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n // A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the\n // engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the\n // dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.\n parallelGroup: text('parallel_group'),\n});\n\nexport const bufferedSignals = sqliteTable('durable_buffered_signals', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n token: text('token').notNull(),\n payload: text('payload', { mode: 'json' }),\n});\n\nexport const durableSchema = {\n workflowRuns,\n stepCheckpoints,\n runAttributes,\n signalWaiters,\n bufferedSignals,\n};\n\n/**\n * Tables this store creates and manages (you run the migrations — see the package README — but\n * these are the fixed set `durableSchema` declares). Feed to your ORM's migration differ\n * exclude/skipTables so it never tries to drop them.\n *\n * ```ts\n * // MikroORM-flavoured example (Drizzle Kit has no built-in equivalent option); adapt to whichever\n * // migration tool generates your diffs.\n * const skipTables = new Set(durableManagedTables());\n * ```\n *\n * Derived from {@link durableSchema} via drizzle-orm's own `getTableName` — one list, so a\n * consumer's denylist can never drift from the table names declared above.\n */\nexport function durableManagedTables(): string[] {\n return Object.values(durableSchema).map((table) => getTableName(table));\n}\n"],"mappings":"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","names":["import_drizzle_orm","workflowRuns","sqliteTable","id","text","primaryKey","workflow","notNull","workflowVersion","status","input","mode","output","error","wakeAt","integer","lockedBy","lockedUntil","awaitingDecisionTaskId","recoveryAttempts","tags","$type","searchAttributes","priority","createdAt","updatedAt","stepCheckpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","parallelGroup","enqueuedAt","startedAt","finishedAt","t","columns","runAttributes","key","strValue","numValue","real","signalWaiters","token","bufferedSignals","autoIncrement","payload","durableSchema","durableManagedTables","Object","values","map","table","getTableName","DrizzleStateStore","db","createRun","run","insert","workflowRuns","values","toRunRow","reindexAttributes","id","searchAttributes","updateRun","runId","patch","row","toRunPatch","Object","keys","length","update","set","where","eq","attributes","delete","runAttributes","rows","normalizeAttributeRows","getRun","select","from","limit","fromRunRow","deleteRun","stepCheckpoints","signalWaiters","getCheckpoint","seq","and","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointRow","onConflictDoUpdate","target","transaction","work","tx","raw","cp","listIncompleteRuns","inArray","status","map","listPendingRuns","orderBy","asc","createdAt","listDueTimers","nowMs","isNotNull","wakeAt","lte","tryLockRun","owner","leaseUntilMs","result","lockedBy","lockedUntil","or","isNull","changes","releaseRunLock","renewRunLock","listRuns","query","filters","workflow","undefined","statuses","sql","tag","like","tags","f","attributeExists","filter","desc","offset","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","exists","one","key","attributeOperand","listCheckpoints","getLatestCheckpointByName","name","listCheckpointsByNamePrefix","prefixes","p","putSignalWaiter","waiter","token","parallelGroup","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","awaitingDecisionTaskId","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -232,6 +232,25 @@ declare const workflowRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
232
232
|
identity: undefined;
|
|
233
233
|
generated: undefined;
|
|
234
234
|
}, {}, {}>;
|
|
235
|
+
awaitingDecisionTaskId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
236
|
+
name: "awaiting_decision_task_id";
|
|
237
|
+
tableName: "durable_workflow_runs";
|
|
238
|
+
dataType: "string";
|
|
239
|
+
columnType: "SQLiteText";
|
|
240
|
+
data: string;
|
|
241
|
+
driverParam: string;
|
|
242
|
+
notNull: false;
|
|
243
|
+
hasDefault: false;
|
|
244
|
+
isPrimaryKey: false;
|
|
245
|
+
isAutoincrement: false;
|
|
246
|
+
hasRuntimeDefault: false;
|
|
247
|
+
enumValues: [string, ...string[]];
|
|
248
|
+
baseColumn: never;
|
|
249
|
+
identity: undefined;
|
|
250
|
+
generated: undefined;
|
|
251
|
+
}, {}, {
|
|
252
|
+
length: number | undefined;
|
|
253
|
+
}>;
|
|
235
254
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
236
255
|
name: "recovery_attempts";
|
|
237
256
|
tableName: "durable_workflow_runs";
|
|
@@ -1058,6 +1077,25 @@ declare const durableSchema: {
|
|
|
1058
1077
|
identity: undefined;
|
|
1059
1078
|
generated: undefined;
|
|
1060
1079
|
}, {}, {}>;
|
|
1080
|
+
awaitingDecisionTaskId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1081
|
+
name: "awaiting_decision_task_id";
|
|
1082
|
+
tableName: "durable_workflow_runs";
|
|
1083
|
+
dataType: "string";
|
|
1084
|
+
columnType: "SQLiteText";
|
|
1085
|
+
data: string;
|
|
1086
|
+
driverParam: string;
|
|
1087
|
+
notNull: false;
|
|
1088
|
+
hasDefault: false;
|
|
1089
|
+
isPrimaryKey: false;
|
|
1090
|
+
isAutoincrement: false;
|
|
1091
|
+
hasRuntimeDefault: false;
|
|
1092
|
+
enumValues: [string, ...string[]];
|
|
1093
|
+
baseColumn: never;
|
|
1094
|
+
identity: undefined;
|
|
1095
|
+
generated: undefined;
|
|
1096
|
+
}, {}, {
|
|
1097
|
+
length: number | undefined;
|
|
1098
|
+
}>;
|
|
1061
1099
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1062
1100
|
name: "recovery_attempts";
|
|
1063
1101
|
tableName: "durable_workflow_runs";
|
|
@@ -1700,5 +1738,20 @@ declare const durableSchema: {
|
|
|
1700
1738
|
dialect: "sqlite";
|
|
1701
1739
|
}>;
|
|
1702
1740
|
};
|
|
1741
|
+
/**
|
|
1742
|
+
* Tables this store creates and manages (you run the migrations — see the package README — but
|
|
1743
|
+
* these are the fixed set `durableSchema` declares). Feed to your ORM's migration differ
|
|
1744
|
+
* exclude/skipTables so it never tries to drop them.
|
|
1745
|
+
*
|
|
1746
|
+
* ```ts
|
|
1747
|
+
* // MikroORM-flavoured example (Drizzle Kit has no built-in equivalent option); adapt to whichever
|
|
1748
|
+
* // migration tool generates your diffs.
|
|
1749
|
+
* const skipTables = new Set(durableManagedTables());
|
|
1750
|
+
* ```
|
|
1751
|
+
*
|
|
1752
|
+
* Derived from {@link durableSchema} via drizzle-orm's own `getTableName` — one list, so a
|
|
1753
|
+
* consumer's denylist can never drift from the table names declared above.
|
|
1754
|
+
*/
|
|
1755
|
+
declare function durableManagedTables(): string[];
|
|
1703
1756
|
|
|
1704
|
-
export { DrizzleStateStore, bufferedSignals, durableSchema, runAttributes, signalWaiters, stepCheckpoints, workflowRuns };
|
|
1757
|
+
export { DrizzleStateStore, bufferedSignals, durableManagedTables, durableSchema, runAttributes, signalWaiters, stepCheckpoints, workflowRuns };
|
package/dist/index.d.ts
CHANGED
|
@@ -232,6 +232,25 @@ declare const workflowRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
232
232
|
identity: undefined;
|
|
233
233
|
generated: undefined;
|
|
234
234
|
}, {}, {}>;
|
|
235
|
+
awaitingDecisionTaskId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
236
|
+
name: "awaiting_decision_task_id";
|
|
237
|
+
tableName: "durable_workflow_runs";
|
|
238
|
+
dataType: "string";
|
|
239
|
+
columnType: "SQLiteText";
|
|
240
|
+
data: string;
|
|
241
|
+
driverParam: string;
|
|
242
|
+
notNull: false;
|
|
243
|
+
hasDefault: false;
|
|
244
|
+
isPrimaryKey: false;
|
|
245
|
+
isAutoincrement: false;
|
|
246
|
+
hasRuntimeDefault: false;
|
|
247
|
+
enumValues: [string, ...string[]];
|
|
248
|
+
baseColumn: never;
|
|
249
|
+
identity: undefined;
|
|
250
|
+
generated: undefined;
|
|
251
|
+
}, {}, {
|
|
252
|
+
length: number | undefined;
|
|
253
|
+
}>;
|
|
235
254
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
236
255
|
name: "recovery_attempts";
|
|
237
256
|
tableName: "durable_workflow_runs";
|
|
@@ -1058,6 +1077,25 @@ declare const durableSchema: {
|
|
|
1058
1077
|
identity: undefined;
|
|
1059
1078
|
generated: undefined;
|
|
1060
1079
|
}, {}, {}>;
|
|
1080
|
+
awaitingDecisionTaskId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1081
|
+
name: "awaiting_decision_task_id";
|
|
1082
|
+
tableName: "durable_workflow_runs";
|
|
1083
|
+
dataType: "string";
|
|
1084
|
+
columnType: "SQLiteText";
|
|
1085
|
+
data: string;
|
|
1086
|
+
driverParam: string;
|
|
1087
|
+
notNull: false;
|
|
1088
|
+
hasDefault: false;
|
|
1089
|
+
isPrimaryKey: false;
|
|
1090
|
+
isAutoincrement: false;
|
|
1091
|
+
hasRuntimeDefault: false;
|
|
1092
|
+
enumValues: [string, ...string[]];
|
|
1093
|
+
baseColumn: never;
|
|
1094
|
+
identity: undefined;
|
|
1095
|
+
generated: undefined;
|
|
1096
|
+
}, {}, {
|
|
1097
|
+
length: number | undefined;
|
|
1098
|
+
}>;
|
|
1061
1099
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1062
1100
|
name: "recovery_attempts";
|
|
1063
1101
|
tableName: "durable_workflow_runs";
|
|
@@ -1700,5 +1738,20 @@ declare const durableSchema: {
|
|
|
1700
1738
|
dialect: "sqlite";
|
|
1701
1739
|
}>;
|
|
1702
1740
|
};
|
|
1741
|
+
/**
|
|
1742
|
+
* Tables this store creates and manages (you run the migrations — see the package README — but
|
|
1743
|
+
* these are the fixed set `durableSchema` declares). Feed to your ORM's migration differ
|
|
1744
|
+
* exclude/skipTables so it never tries to drop them.
|
|
1745
|
+
*
|
|
1746
|
+
* ```ts
|
|
1747
|
+
* // MikroORM-flavoured example (Drizzle Kit has no built-in equivalent option); adapt to whichever
|
|
1748
|
+
* // migration tool generates your diffs.
|
|
1749
|
+
* const skipTables = new Set(durableManagedTables());
|
|
1750
|
+
* ```
|
|
1751
|
+
*
|
|
1752
|
+
* Derived from {@link durableSchema} via drizzle-orm's own `getTableName` — one list, so a
|
|
1753
|
+
* consumer's denylist can never drift from the table names declared above.
|
|
1754
|
+
*/
|
|
1755
|
+
declare function durableManagedTables(): string[];
|
|
1703
1756
|
|
|
1704
|
-
export { DrizzleStateStore, bufferedSignals, durableSchema, runAttributes, signalWaiters, stepCheckpoints, workflowRuns };
|
|
1757
|
+
export { DrizzleStateStore, bufferedSignals, durableManagedTables, durableSchema, runAttributes, signalWaiters, stepCheckpoints, workflowRuns };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { attributeColumnFor, attributeOperand, normalizeAttributeRows, sqlCompar
|
|
|
6
6
|
import { and, asc, desc, eq, exists, inArray, isNotNull, isNull, like, lte, or, sql } from "drizzle-orm";
|
|
7
7
|
|
|
8
8
|
// src/schema.ts
|
|
9
|
+
import { getTableName } from "drizzle-orm";
|
|
9
10
|
import { integer, primaryKey, real, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
10
11
|
var workflowRuns = sqliteTable("durable_workflow_runs", {
|
|
11
12
|
id: text("id").primaryKey(),
|
|
@@ -24,6 +25,9 @@ var workflowRuns = sqliteTable("durable_workflow_runs", {
|
|
|
24
25
|
wakeAt: integer("wake_at"),
|
|
25
26
|
lockedBy: text("locked_by"),
|
|
26
27
|
lockedUntil: integer("locked_until"),
|
|
28
|
+
// REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so
|
|
29
|
+
// only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.
|
|
30
|
+
awaitingDecisionTaskId: text("awaiting_decision_task_id"),
|
|
27
31
|
recoveryAttempts: integer("recovery_attempts"),
|
|
28
32
|
tags: text("tags", {
|
|
29
33
|
mode: "json"
|
|
@@ -109,6 +113,10 @@ var durableSchema = {
|
|
|
109
113
|
signalWaiters,
|
|
110
114
|
bufferedSignals
|
|
111
115
|
};
|
|
116
|
+
function durableManagedTables() {
|
|
117
|
+
return Object.values(durableSchema).map((table) => getTableName(table));
|
|
118
|
+
}
|
|
119
|
+
__name(durableManagedTables, "durableManagedTables");
|
|
112
120
|
|
|
113
121
|
// src/drizzle-state-store.ts
|
|
114
122
|
var DrizzleStateStore = class {
|
|
@@ -312,6 +320,7 @@ function toRunRow(run) {
|
|
|
312
320
|
wakeAt: run.wakeAt ?? null,
|
|
313
321
|
lockedBy: run.lockedBy ?? null,
|
|
314
322
|
lockedUntil: run.lockedUntil ?? null,
|
|
323
|
+
awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,
|
|
315
324
|
recoveryAttempts: run.recoveryAttempts ?? null,
|
|
316
325
|
tags: run.tags ?? null,
|
|
317
326
|
searchAttributes: run.searchAttributes ?? null,
|
|
@@ -332,6 +341,7 @@ function toRunPatch(patch) {
|
|
|
332
341
|
if ("wakeAt" in patch) row.wakeAt = patch.wakeAt ?? null;
|
|
333
342
|
if ("lockedBy" in patch) row.lockedBy = patch.lockedBy ?? null;
|
|
334
343
|
if ("lockedUntil" in patch) row.lockedUntil = patch.lockedUntil ?? null;
|
|
344
|
+
if ("awaitingDecisionTaskId" in patch) row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;
|
|
335
345
|
if ("recoveryAttempts" in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;
|
|
336
346
|
if ("tags" in patch) row.tags = patch.tags ?? null;
|
|
337
347
|
if ("searchAttributes" in patch) row.searchAttributes = patch.searchAttributes ?? null;
|
|
@@ -353,6 +363,7 @@ function fromRunRow(row) {
|
|
|
353
363
|
wakeAt: row.wakeAt ?? void 0,
|
|
354
364
|
lockedBy: row.lockedBy ?? void 0,
|
|
355
365
|
lockedUntil: row.lockedUntil ?? void 0,
|
|
366
|
+
awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? void 0,
|
|
356
367
|
recoveryAttempts: row.recoveryAttempts ?? void 0,
|
|
357
368
|
tags: row.tags ?? void 0,
|
|
358
369
|
searchAttributes: row.searchAttributes ?? void 0,
|
|
@@ -409,6 +420,7 @@ __name(fromCheckpointRow, "fromCheckpointRow");
|
|
|
409
420
|
export {
|
|
410
421
|
DrizzleStateStore,
|
|
411
422
|
bufferedSignals,
|
|
423
|
+
durableManagedTables,
|
|
412
424
|
durableSchema,
|
|
413
425
|
runAttributes,
|
|
414
426
|
signalWaiters,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/drizzle-state-store.ts","../src/schema.ts"],"sourcesContent":["import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n inArray,\n isNotNull,\n isNull,\n like,\n lte,\n or,\n sql,\n} from 'drizzle-orm';\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';\nimport {\n bufferedSignals,\n runAttributes,\n signalWaiters,\n stepCheckpoints,\n workflowRuns,\n} from './schema';\n\ntype RunRow = typeof workflowRuns.$inferSelect;\ntype CheckpointRow = typeof stepCheckpoints.$inferSelect;\ntype DrizzleSqlite = BaseSQLiteDatabase<'sync' | 'async', unknown>;\n\n/**\n * Drizzle (SQLite / libSQL) `StateStore`. Pass a drizzle db built with `./schema`. Timestamps are\n * epoch-ms integers (SQLite's 64-bit integers hold them fine). For Postgres or MySQL, use the\n * MikroORM, TypeORM or Prisma adapter.\n */\nexport class DrizzleStateStore implements StateStore {\n constructor(private readonly db: DrizzleSqlite) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.insert(workflowRuns).values(toRunRow(run));\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const row = toRunPatch(patch);\n // Drizzle throws on `.set({})`; skip the UPDATE when no mapped column actually changed.\n if (Object.keys(row).length)\n await this.db.update(workflowRuns).set(row).where(eq(workflowRuns.id, runId));\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n ): Promise<void> {\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.insert(runAttributes).values(rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.id, runId))\n .limit(1);\n return rows[0] ? fromRunRow(rows[0]) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.delete(stepCheckpoints).where(eq(stepCheckpoints.runId, runId));\n await this.db.delete(signalWaiters).where(eq(signalWaiters.runId, runId));\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n await this.db.delete(workflowRuns).where(eq(workflowRuns.id, runId));\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.seq, seq)))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const row = toCheckpointRow(checkpoint);\n await this.db\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({ target: [stepCheckpoints.runId, stepCheckpoints.seq], set: row });\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.db.transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const row = toCheckpointRow(cp);\n await tx\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({\n target: [stepCheckpoints.runId, stepCheckpoints.seq],\n set: row,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(inArray(workflowRuns.status, ['running', 'cancelling']));\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.status, 'pending'))\n .orderBy(asc(workflowRuns.createdAt)) // FIFO dispatch\n .limit(limit);\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(\n and(\n eq(workflowRuns.status, 'suspended'),\n isNotNull(workflowRuns.wakeAt),\n lte(workflowRuns.wakeAt, nowMs),\n ),\n );\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedBy: owner, lockedUntil: leaseUntilMs })\n .where(\n and(\n eq(workflowRuns.id, runId),\n or(isNull(workflowRuns.lockedUntil), lte(workflowRuns.lockedUntil, nowMs)),\n ),\n );\n return (result as { changes?: number }).changes === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db\n .update(workflowRuns)\n .set({ lockedBy: null, lockedUntil: null })\n .where(eq(workflowRuns.id, runId));\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedUntil: leaseUntilMs })\n .where(and(eq(workflowRuns.id, runId), eq(workflowRuns.lockedBy, owner)));\n return (result as { changes?: number }).changes === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const filters = [\n query.workflow ? eq(workflowRuns.workflow, query.workflow) : undefined,\n query.status ? eq(workflowRuns.status, query.status) : undefined,\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store).\n query.statuses\n ? query.statuses.length\n ? inArray(workflowRuns.status, query.statuses)\n : sql`1 = 0`\n : undefined,\n // `tags` is JSON text; match the quoted token so `etl` doesn't match `etl-foo`.\n query.tag ? like(workflowRuns.tags, `%\"${query.tag}\"%`) : undefined,\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes an EXISTS against\n // the normalized `durable_run_attributes` side-table, so the DB filters AND paginates — no\n // full scan + in-process filter. ANDed: a run must satisfy every filter (one EXISTS per filter).\n ...(query.attributes?.map((f) => this.attributeExists(f)) ?? []),\n ].filter((f): f is NonNullable<typeof f> => f !== undefined);\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(filters.length ? and(...filters) : undefined)\n .orderBy(desc(workflowRuns.createdAt)) // newest first — recent runs on top in the dashboard\n .limit(query.limit ?? -1)\n .offset(query.offset ?? 0);\n return rows.map(fromRunRow);\n }\n\n /** One attribute predicate as an EXISTS subquery on the side-table, correlated to the outer run.\n * `<>` (ne) also excludes runs where the attribute is absent (the missing-key-never-matches\n * contract): EXISTS already requires the key row to be present, so EXISTS(... <> ...) is exactly\n * ne-with-present. Numeric operands compare `num_value`, everything else `str_value`. */\n private attributeExists(f: AttributeFilter) {\n const col =\n attributeColumnFor(f) === 'numValue' ? runAttributes.numValue : runAttributes.strValue;\n const cmp = sqlComparator(f.op);\n return exists(\n this.db\n .select({ one: sql`1` })\n .from(runAttributes)\n .where(\n and(\n eq(runAttributes.runId, workflowRuns.id),\n eq(runAttributes.key, f.key),\n sql`${col} ${sql.raw(cmp)} ${attributeOperand(f)}`,\n ),\n ),\n );\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(eq(stepCheckpoints.runId, runId))\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.name, name)))\n .orderBy(desc(stepCheckpoints.seq))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(\n and(\n eq(stepCheckpoints.runId, runId),\n or(...prefixes.map((p) => like(stepCheckpoints.name, `${p}%`))),\n ),\n )\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db\n .insert(signalWaiters)\n .values({\n token: waiter.token,\n runId: waiter.runId,\n seq: waiter.seq,\n parallelGroup: waiter.parallelGroup ?? null,\n })\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq, parallelGroup: waiter.parallelGroup ?? null },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(eq(signalWaiters.token, token))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(signalWaiters).where(eq(signalWaiters.token, token));\n return {\n token: row.token,\n runId: row.runId,\n seq: row.seq,\n parallelGroup: row.parallelGroup ?? undefined,\n };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(like(signalWaiters.token, `${prefix}%`));\n return rows.map((r) => ({\n token: r.token,\n runId: r.runId,\n seq: r.seq,\n parallelGroup: r.parallelGroup ?? undefined,\n }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.insert(bufferedSignals).values({ token, payload: payload ?? null });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const rows = await this.db\n .select()\n .from(bufferedSignals)\n .where(eq(bufferedSignals.token, token))\n .orderBy(asc(bufferedSignals.id))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(bufferedSignals).where(eq(bufferedSignals.id, row.id));\n return { payload: row.payload ?? undefined };\n }\n}\n\nfunction toRunRow(run: WorkflowRun): RunRow {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: run.input ?? null,\n output: run.output ?? null,\n error: run.error ?? null,\n wakeAt: run.wakeAt ?? null,\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil ?? null,\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: run.tags ?? null,\n searchAttributes: run.searchAttributes ?? null,\n priority: run.priority ?? null,\n createdAt: run.createdAt.getTime(),\n updatedAt: run.updatedAt.getTime(),\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>): Partial<RunRow> {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const row: Partial<RunRow> = {};\n if ('workflow' in patch) row.workflow = patch.workflow;\n if ('workflowVersion' in patch) row.workflowVersion = patch.workflowVersion;\n if ('status' in patch) row.status = patch.status;\n if ('input' in patch) row.input = patch.input ?? null;\n if ('output' in patch) row.output = patch.output ?? null;\n if ('error' in patch) row.error = patch.error ?? null;\n if ('wakeAt' in patch) row.wakeAt = patch.wakeAt ?? null;\n if ('lockedBy' in patch) row.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch) row.lockedUntil = patch.lockedUntil ?? null;\n if ('recoveryAttempts' in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) row.tags = patch.tags ?? null;\n if ('searchAttributes' in patch) row.searchAttributes = patch.searchAttributes ?? null;\n if ('priority' in patch) row.priority = patch.priority ?? null;\n if (patch.createdAt != null) row.createdAt = patch.createdAt.getTime();\n if (patch.updatedAt != null) row.updatedAt = patch.updatedAt.getTime();\n return row;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: row.wakeAt ?? undefined,\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil ?? undefined,\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: row.tags ?? undefined,\n searchAttributes: row.searchAttributes ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: new Date(row.createdAt),\n updatedAt: new Date(row.updatedAt),\n };\n}\n\nfunction toCheckpointRow(cp: StepCheckpoint): CheckpointRow {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: cp.input ?? null,\n output: cp.output ?? null,\n error: cp.error ?? null,\n events: cp.events ?? null,\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n parallelGroup: cp.parallelGroup ?? null,\n wakeAt: cp.wakeAt ?? null,\n enqueuedAt: (cp.enqueuedAt ?? cp.startedAt).getTime(),\n startedAt: cp.startedAt.getTime(),\n finishedAt: cp.finishedAt.getTime(),\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n parallelGroup: row.parallelGroup ?? undefined,\n wakeAt: row.wakeAt ?? undefined,\n enqueuedAt: row.enqueuedAt == null ? new Date(row.startedAt) : new Date(row.enqueuedAt),\n startedAt: new Date(row.startedAt),\n finishedAt: new Date(row.finishedAt),\n };\n}\n","import { integer, primaryKey, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';\n\n// SQLite / libSQL schema for the durable tables. Timestamps and `wakeAt` are epoch-ms integers\n// (SQLite has no native date type). Import these tables and pass them with your drizzle db.\n\nexport const workflowRuns = sqliteTable('durable_workflow_runs', {\n id: text('id').primaryKey(),\n workflow: text('workflow').notNull(),\n workflowVersion: text('workflow_version').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n wakeAt: integer('wake_at'),\n lockedBy: text('locked_by'),\n lockedUntil: integer('locked_until'),\n recoveryAttempts: integer('recovery_attempts'),\n tags: text('tags', { mode: 'json' }).$type<string[]>(),\n searchAttributes: text('search_attributes', { mode: 'json' }).$type<\n Record<string, string | number | boolean>\n >(),\n priority: integer('priority'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n\nexport const stepCheckpoints = sqliteTable(\n 'durable_step_checkpoints',\n {\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n name: text('name').notNull(),\n kind: text('kind').notNull(),\n stepId: text('step_id').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n events: text('events', { mode: 'json' }),\n attempts: integer('attempts').notNull(),\n workerGroup: text('worker_group'),\n // A ctx.gather/ctx.all fan tags every sibling step with the same group so the dashboard renders\n // them as one parallel group; the core engine sets it (incl. from a remote worker's recordStep).\n parallelGroup: text('parallel_group'),\n wakeAt: integer('wake_at'),\n enqueuedAt: integer('enqueued_at'),\n startedAt: integer('started_at').notNull(),\n finishedAt: integer('finished_at').notNull(),\n },\n (t) => [primaryKey({ columns: [t.runId, t.seq] })],\n);\n\n// Normalized search-attribute side-table: one row per (run, key), so range/equality attribute\n// predicates push DOWN into SQL via an EXISTS join instead of a coarse scan + in-process filter.\n// Maintained on every createRun/updateRun. Numbers land in `numValue`, strings/booleans in\n// `strValue` (booleans as \"true\"/\"false\"); see core `normalizeAttributeRows`.\nexport const runAttributes = sqliteTable(\n 'durable_run_attributes',\n {\n runId: text('run_id').notNull(),\n key: text('key').notNull(),\n strValue: text('str_value'),\n numValue: real('num_value'),\n },\n (t) => [primaryKey({ columns: [t.runId, t.key] })],\n);\n\nexport const signalWaiters = sqliteTable('durable_signal_waiters', {\n token: text('token').primaryKey(),\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n // A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the\n // engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the\n // dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.\n parallelGroup: text('parallel_group'),\n});\n\nexport const bufferedSignals = sqliteTable('durable_buffered_signals', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n token: text('token').notNull(),\n payload: text('payload', { mode: 'json' }),\n});\n\nexport const durableSchema = {\n workflowRuns,\n stepCheckpoints,\n runAttributes,\n signalWaiters,\n bufferedSignals,\n};\n"],"mappings":"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","names":["attributeColumnFor","attributeOperand","normalizeAttributeRows","sqlComparator","and","asc","desc","eq","exists","inArray","isNotNull","isNull","like","lte","or","sql","integer","primaryKey","real","sqliteTable","text","workflowRuns","id","workflow","notNull","workflowVersion","status","input","mode","output","error","wakeAt","lockedBy","lockedUntil","recoveryAttempts","tags","$type","searchAttributes","priority","createdAt","updatedAt","stepCheckpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","parallelGroup","enqueuedAt","startedAt","finishedAt","t","columns","runAttributes","key","strValue","numValue","signalWaiters","token","bufferedSignals","autoIncrement","payload","durableSchema","DrizzleStateStore","db","createRun","run","insert","workflowRuns","values","toRunRow","reindexAttributes","id","searchAttributes","updateRun","runId","patch","row","toRunPatch","Object","keys","length","update","set","where","eq","attributes","delete","runAttributes","rows","normalizeAttributeRows","getRun","select","from","limit","fromRunRow","deleteRun","stepCheckpoints","signalWaiters","getCheckpoint","seq","and","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointRow","onConflictDoUpdate","target","transaction","work","tx","raw","cp","listIncompleteRuns","inArray","status","map","listPendingRuns","orderBy","asc","createdAt","listDueTimers","nowMs","isNotNull","wakeAt","lte","tryLockRun","owner","leaseUntilMs","result","lockedBy","lockedUntil","or","isNull","changes","releaseRunLock","renewRunLock","listRuns","query","filters","workflow","undefined","statuses","sql","tag","like","tags","f","attributeExists","filter","desc","offset","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","exists","one","key","attributeOperand","listCheckpoints","getLatestCheckpointByName","name","listCheckpointsByNamePrefix","prefixes","p","putSignalWaiter","waiter","token","parallelGroup","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
|
|
1
|
+
{"version":3,"sources":["../src/drizzle-state-store.ts","../src/schema.ts"],"sourcesContent":["import {\n type AttributeFilter,\n type RunQuery,\n type SignalWaiter,\n type StateStore,\n type StepCheckpoint,\n type StepError,\n type StepEvent,\n type WorkflowRun,\n attributeColumnFor,\n attributeOperand,\n normalizeAttributeRows,\n sqlComparator,\n} from '@dudousxd/nestjs-durable-core';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n inArray,\n isNotNull,\n isNull,\n like,\n lte,\n or,\n sql,\n} from 'drizzle-orm';\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';\nimport {\n bufferedSignals,\n runAttributes,\n signalWaiters,\n stepCheckpoints,\n workflowRuns,\n} from './schema';\n\ntype RunRow = typeof workflowRuns.$inferSelect;\ntype CheckpointRow = typeof stepCheckpoints.$inferSelect;\ntype DrizzleSqlite = BaseSQLiteDatabase<'sync' | 'async', unknown>;\n\n/**\n * Drizzle (SQLite / libSQL) `StateStore`. Pass a drizzle db built with `./schema`. Timestamps are\n * epoch-ms integers (SQLite's 64-bit integers hold them fine). For Postgres or MySQL, use the\n * MikroORM, TypeORM or Prisma adapter.\n */\nexport class DrizzleStateStore implements StateStore {\n constructor(private readonly db: DrizzleSqlite) {}\n\n async createRun(run: WorkflowRun): Promise<void> {\n await this.db.insert(workflowRuns).values(toRunRow(run));\n await this.reindexAttributes(run.id, run.searchAttributes);\n }\n\n async updateRun(runId: string, patch: Partial<WorkflowRun>): Promise<void> {\n const row = toRunPatch(patch);\n // Drizzle throws on `.set({})`; skip the UPDATE when no mapped column actually changed.\n if (Object.keys(row).length)\n await this.db.update(workflowRuns).set(row).where(eq(workflowRuns.id, runId));\n // Keep the side-table in step with the run's attributes whenever they're patched.\n if ('searchAttributes' in patch) await this.reindexAttributes(runId, patch.searchAttributes);\n }\n\n /** Rewrite a run's normalized attribute rows: delete the old set, insert the current one. Mirrors\n * the in-memory store's reindex so the side-table always reflects the run's live searchAttributes. */\n private async reindexAttributes(\n runId: string,\n attributes: WorkflowRun['searchAttributes'],\n ): Promise<void> {\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n const rows = normalizeAttributeRows(runId, attributes);\n if (rows.length) await this.db.insert(runAttributes).values(rows);\n }\n\n async getRun(runId: string): Promise<WorkflowRun | null> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.id, runId))\n .limit(1);\n return rows[0] ? fromRunRow(rows[0]) : null;\n }\n\n async deleteRun(runId: string): Promise<void> {\n // Child rows first, then the run — checkpoints, signal waiters, attribute rows.\n await this.db.delete(stepCheckpoints).where(eq(stepCheckpoints.runId, runId));\n await this.db.delete(signalWaiters).where(eq(signalWaiters.runId, runId));\n await this.db.delete(runAttributes).where(eq(runAttributes.runId, runId));\n await this.db.delete(workflowRuns).where(eq(workflowRuns.id, runId));\n }\n\n async getCheckpoint(runId: string, seq: number): Promise<StepCheckpoint | null> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.seq, seq)))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : null;\n }\n\n async saveCheckpoint(checkpoint: StepCheckpoint): Promise<void> {\n const row = toCheckpointRow(checkpoint);\n await this.db\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({ target: [stepCheckpoints.runId, stepCheckpoints.seq], set: row });\n }\n\n async transaction<T>(\n work: (tx: {\n raw: unknown;\n saveCheckpoint: (cp: StepCheckpoint) => Promise<void>;\n }) => Promise<T>,\n ): Promise<T> {\n return this.db.transaction(async (tx) =>\n work({\n raw: tx,\n saveCheckpoint: async (cp) => {\n const row = toCheckpointRow(cp);\n await tx\n .insert(stepCheckpoints)\n .values(row)\n .onConflictDoUpdate({\n target: [stepCheckpoints.runId, stepCheckpoints.seq],\n set: row,\n });\n },\n }),\n );\n }\n\n async listIncompleteRuns(): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(inArray(workflowRuns.status, ['running', 'cancelling']));\n return rows.map(fromRunRow);\n }\n\n async listPendingRuns(limit: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(eq(workflowRuns.status, 'pending'))\n .orderBy(asc(workflowRuns.createdAt)) // FIFO dispatch\n .limit(limit);\n return rows.map(fromRunRow);\n }\n\n async listDueTimers(nowMs: number): Promise<WorkflowRun[]> {\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(\n and(\n eq(workflowRuns.status, 'suspended'),\n isNotNull(workflowRuns.wakeAt),\n lte(workflowRuns.wakeAt, nowMs),\n ),\n );\n return rows.map(fromRunRow);\n }\n\n async tryLockRun(\n runId: string,\n owner: string,\n leaseUntilMs: number,\n nowMs: number,\n ): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedBy: owner, lockedUntil: leaseUntilMs })\n .where(\n and(\n eq(workflowRuns.id, runId),\n or(isNull(workflowRuns.lockedUntil), lte(workflowRuns.lockedUntil, nowMs)),\n ),\n );\n return (result as { changes?: number }).changes === 1;\n }\n\n async releaseRunLock(runId: string): Promise<void> {\n await this.db\n .update(workflowRuns)\n .set({ lockedBy: null, lockedUntil: null })\n .where(eq(workflowRuns.id, runId));\n }\n\n async renewRunLock(runId: string, owner: string, leaseUntilMs: number): Promise<boolean> {\n const result = await this.db\n .update(workflowRuns)\n .set({ lockedUntil: leaseUntilMs })\n .where(and(eq(workflowRuns.id, runId), eq(workflowRuns.lockedBy, owner)));\n return (result as { changes?: number }).changes === 1;\n }\n\n async listRuns(query: RunQuery): Promise<WorkflowRun[]> {\n const filters = [\n query.workflow ? eq(workflowRuns.workflow, query.workflow) : undefined,\n query.status ? eq(workflowRuns.status, query.status) : undefined,\n // `status IN (...)`; an empty set matches nothing (mirrors the in-memory store).\n query.statuses\n ? query.statuses.length\n ? inArray(workflowRuns.status, query.statuses)\n : sql`1 = 0`\n : undefined,\n // `tags` is JSON text; match the quoted token so `etl` doesn't match `etl-foo`.\n query.tag ? like(workflowRuns.tags, `%\"${query.tag}\"%`) : undefined,\n // Typed/range attribute predicates push DOWN into SQL: each filter becomes an EXISTS against\n // the normalized `durable_run_attributes` side-table, so the DB filters AND paginates — no\n // full scan + in-process filter. ANDed: a run must satisfy every filter (one EXISTS per filter).\n ...(query.attributes?.map((f) => this.attributeExists(f)) ?? []),\n ].filter((f): f is NonNullable<typeof f> => f !== undefined);\n const rows = await this.db\n .select()\n .from(workflowRuns)\n .where(filters.length ? and(...filters) : undefined)\n .orderBy(desc(workflowRuns.createdAt)) // newest first — recent runs on top in the dashboard\n .limit(query.limit ?? -1)\n .offset(query.offset ?? 0);\n return rows.map(fromRunRow);\n }\n\n /** One attribute predicate as an EXISTS subquery on the side-table, correlated to the outer run.\n * `<>` (ne) also excludes runs where the attribute is absent (the missing-key-never-matches\n * contract): EXISTS already requires the key row to be present, so EXISTS(... <> ...) is exactly\n * ne-with-present. Numeric operands compare `num_value`, everything else `str_value`. */\n private attributeExists(f: AttributeFilter) {\n const col =\n attributeColumnFor(f) === 'numValue' ? runAttributes.numValue : runAttributes.strValue;\n const cmp = sqlComparator(f.op);\n return exists(\n this.db\n .select({ one: sql`1` })\n .from(runAttributes)\n .where(\n and(\n eq(runAttributes.runId, workflowRuns.id),\n eq(runAttributes.key, f.key),\n sql`${col} ${sql.raw(cmp)} ${attributeOperand(f)}`,\n ),\n ),\n );\n }\n\n async listCheckpoints(runId: string): Promise<StepCheckpoint[]> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(eq(stepCheckpoints.runId, runId))\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async getLatestCheckpointByName(\n runId: string,\n name: string,\n ): Promise<StepCheckpoint | undefined> {\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(and(eq(stepCheckpoints.runId, runId), eq(stepCheckpoints.name, name)))\n .orderBy(desc(stepCheckpoints.seq))\n .limit(1);\n return rows[0] ? fromCheckpointRow(rows[0]) : undefined;\n }\n\n async listCheckpointsByNamePrefix(runId: string, prefixes: string[]): Promise<StepCheckpoint[]> {\n if (prefixes.length === 0) return [];\n const rows = await this.db\n .select()\n .from(stepCheckpoints)\n .where(\n and(\n eq(stepCheckpoints.runId, runId),\n or(...prefixes.map((p) => like(stepCheckpoints.name, `${p}%`))),\n ),\n )\n .orderBy(asc(stepCheckpoints.seq));\n return rows.map(fromCheckpointRow);\n }\n\n async putSignalWaiter(waiter: SignalWaiter): Promise<void> {\n await this.db\n .insert(signalWaiters)\n .values({\n token: waiter.token,\n runId: waiter.runId,\n seq: waiter.seq,\n parallelGroup: waiter.parallelGroup ?? null,\n })\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq, parallelGroup: waiter.parallelGroup ?? null },\n });\n }\n\n async takeSignalWaiter(token: string): Promise<SignalWaiter | null> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(eq(signalWaiters.token, token))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(signalWaiters).where(eq(signalWaiters.token, token));\n return {\n token: row.token,\n runId: row.runId,\n seq: row.seq,\n parallelGroup: row.parallelGroup ?? undefined,\n };\n }\n\n async listSignalWaiters(prefix: string): Promise<SignalWaiter[]> {\n const rows = await this.db\n .select()\n .from(signalWaiters)\n .where(like(signalWaiters.token, `${prefix}%`));\n return rows.map((r) => ({\n token: r.token,\n runId: r.runId,\n seq: r.seq,\n parallelGroup: r.parallelGroup ?? undefined,\n }));\n }\n\n async bufferSignal(token: string, payload: unknown): Promise<void> {\n await this.db.insert(bufferedSignals).values({ token, payload: payload ?? null });\n }\n\n async takeBufferedSignal(token: string): Promise<{ payload: unknown } | null> {\n const rows = await this.db\n .select()\n .from(bufferedSignals)\n .where(eq(bufferedSignals.token, token))\n .orderBy(asc(bufferedSignals.id))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await this.db.delete(bufferedSignals).where(eq(bufferedSignals.id, row.id));\n return { payload: row.payload ?? undefined };\n }\n}\n\nfunction toRunRow(run: WorkflowRun): RunRow {\n return {\n id: run.id,\n workflow: run.workflow,\n workflowVersion: run.workflowVersion,\n status: run.status,\n input: run.input ?? null,\n output: run.output ?? null,\n error: run.error ?? null,\n wakeAt: run.wakeAt ?? null,\n lockedBy: run.lockedBy ?? null,\n lockedUntil: run.lockedUntil ?? null,\n awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,\n recoveryAttempts: run.recoveryAttempts ?? null,\n tags: run.tags ?? null,\n searchAttributes: run.searchAttributes ?? null,\n priority: run.priority ?? null,\n createdAt: run.createdAt.getTime(),\n updatedAt: run.updatedAt.getTime(),\n };\n}\n\nfunction toRunPatch(patch: Partial<WorkflowRun>): Partial<RunRow> {\n // Map EVERY patchable field, using presence (`'x' in patch`) semantics for the nullable ones so a\n // patch can CLEAR a column (e.g. `{ error: undefined }` on completion sets it to NULL — matching\n // the TypeORM / MikroORM / in-memory stores). The two non-null Date fields use a defined-guard\n // since they are never cleared. Previously only 7 fields were mapped, so `updateRun({ tags })` /\n // `{ lockedBy }` / clearing `error` silently no-opped on this adapter.\n const row: Partial<RunRow> = {};\n if ('workflow' in patch) row.workflow = patch.workflow;\n if ('workflowVersion' in patch) row.workflowVersion = patch.workflowVersion;\n if ('status' in patch) row.status = patch.status;\n if ('input' in patch) row.input = patch.input ?? null;\n if ('output' in patch) row.output = patch.output ?? null;\n if ('error' in patch) row.error = patch.error ?? null;\n if ('wakeAt' in patch) row.wakeAt = patch.wakeAt ?? null;\n if ('lockedBy' in patch) row.lockedBy = patch.lockedBy ?? null;\n if ('lockedUntil' in patch) row.lockedUntil = patch.lockedUntil ?? null;\n if ('awaitingDecisionTaskId' in patch)\n row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;\n if ('recoveryAttempts' in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;\n if ('tags' in patch) row.tags = patch.tags ?? null;\n if ('searchAttributes' in patch) row.searchAttributes = patch.searchAttributes ?? null;\n if ('priority' in patch) row.priority = patch.priority ?? null;\n if (patch.createdAt != null) row.createdAt = patch.createdAt.getTime();\n if (patch.updatedAt != null) row.updatedAt = patch.updatedAt.getTime();\n return row;\n}\n\nfunction fromRunRow(row: RunRow): WorkflowRun {\n return {\n id: row.id,\n workflow: row.workflow,\n workflowVersion: row.workflowVersion,\n status: row.status as WorkflowRun['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n wakeAt: row.wakeAt ?? undefined,\n lockedBy: row.lockedBy ?? undefined,\n lockedUntil: row.lockedUntil ?? undefined,\n awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? undefined,\n recoveryAttempts: row.recoveryAttempts ?? undefined,\n tags: row.tags ?? undefined,\n searchAttributes: row.searchAttributes ?? undefined,\n priority: row.priority ?? undefined,\n createdAt: new Date(row.createdAt),\n updatedAt: new Date(row.updatedAt),\n };\n}\n\nfunction toCheckpointRow(cp: StepCheckpoint): CheckpointRow {\n return {\n runId: cp.runId,\n seq: cp.seq,\n name: cp.name,\n kind: cp.kind,\n stepId: cp.stepId,\n status: cp.status,\n input: cp.input ?? null,\n output: cp.output ?? null,\n error: cp.error ?? null,\n events: cp.events ?? null,\n attempts: cp.attempts,\n workerGroup: cp.workerGroup ?? null,\n parallelGroup: cp.parallelGroup ?? null,\n wakeAt: cp.wakeAt ?? null,\n enqueuedAt: (cp.enqueuedAt ?? cp.startedAt).getTime(),\n startedAt: cp.startedAt.getTime(),\n finishedAt: cp.finishedAt.getTime(),\n };\n}\n\nfunction fromCheckpointRow(row: CheckpointRow): StepCheckpoint {\n return {\n runId: row.runId,\n seq: row.seq,\n name: row.name,\n kind: row.kind as StepCheckpoint['kind'],\n stepId: row.stepId,\n status: row.status as StepCheckpoint['status'],\n input: row.input ?? undefined,\n output: row.output ?? undefined,\n error: (row.error ?? undefined) as StepError | undefined,\n events: (row.events ?? undefined) as StepEvent[] | undefined,\n attempts: row.attempts,\n workerGroup: row.workerGroup ?? undefined,\n parallelGroup: row.parallelGroup ?? undefined,\n wakeAt: row.wakeAt ?? undefined,\n enqueuedAt: row.enqueuedAt == null ? new Date(row.startedAt) : new Date(row.enqueuedAt),\n startedAt: new Date(row.startedAt),\n finishedAt: new Date(row.finishedAt),\n };\n}\n","import { getTableName } from 'drizzle-orm';\nimport { integer, primaryKey, real, sqliteTable, text } from 'drizzle-orm/sqlite-core';\n\n// SQLite / libSQL schema for the durable tables. Timestamps and `wakeAt` are epoch-ms integers\n// (SQLite has no native date type). Import these tables and pass them with your drizzle db.\n\nexport const workflowRuns = sqliteTable('durable_workflow_runs', {\n id: text('id').primaryKey(),\n workflow: text('workflow').notNull(),\n workflowVersion: text('workflow_version').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n wakeAt: integer('wake_at'),\n lockedBy: text('locked_by'),\n lockedUntil: integer('locked_until'),\n // REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so\n // only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.\n awaitingDecisionTaskId: text('awaiting_decision_task_id'),\n recoveryAttempts: integer('recovery_attempts'),\n tags: text('tags', { mode: 'json' }).$type<string[]>(),\n searchAttributes: text('search_attributes', { mode: 'json' }).$type<\n Record<string, string | number | boolean>\n >(),\n priority: integer('priority'),\n createdAt: integer('created_at').notNull(),\n updatedAt: integer('updated_at').notNull(),\n});\n\nexport const stepCheckpoints = sqliteTable(\n 'durable_step_checkpoints',\n {\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n name: text('name').notNull(),\n kind: text('kind').notNull(),\n stepId: text('step_id').notNull(),\n status: text('status').notNull(),\n input: text('input', { mode: 'json' }),\n output: text('output', { mode: 'json' }),\n error: text('error', { mode: 'json' }),\n events: text('events', { mode: 'json' }),\n attempts: integer('attempts').notNull(),\n workerGroup: text('worker_group'),\n // A ctx.gather/ctx.all fan tags every sibling step with the same group so the dashboard renders\n // them as one parallel group; the core engine sets it (incl. from a remote worker's recordStep).\n parallelGroup: text('parallel_group'),\n wakeAt: integer('wake_at'),\n enqueuedAt: integer('enqueued_at'),\n startedAt: integer('started_at').notNull(),\n finishedAt: integer('finished_at').notNull(),\n },\n (t) => [primaryKey({ columns: [t.runId, t.seq] })],\n);\n\n// Normalized search-attribute side-table: one row per (run, key), so range/equality attribute\n// predicates push DOWN into SQL via an EXISTS join instead of a coarse scan + in-process filter.\n// Maintained on every createRun/updateRun. Numbers land in `numValue`, strings/booleans in\n// `strValue` (booleans as \"true\"/\"false\"); see core `normalizeAttributeRows`.\nexport const runAttributes = sqliteTable(\n 'durable_run_attributes',\n {\n runId: text('run_id').notNull(),\n key: text('key').notNull(),\n strValue: text('str_value'),\n numValue: real('num_value'),\n },\n (t) => [primaryKey({ columns: [t.runId, t.key] })],\n);\n\nexport const signalWaiters = sqliteTable('durable_signal_waiters', {\n token: text('token').primaryKey(),\n runId: text('run_id').notNull(),\n seq: integer('seq').notNull(),\n // A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the\n // engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the\n // dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.\n parallelGroup: text('parallel_group'),\n});\n\nexport const bufferedSignals = sqliteTable('durable_buffered_signals', {\n id: integer('id').primaryKey({ autoIncrement: true }),\n token: text('token').notNull(),\n payload: text('payload', { mode: 'json' }),\n});\n\nexport const durableSchema = {\n workflowRuns,\n stepCheckpoints,\n runAttributes,\n signalWaiters,\n bufferedSignals,\n};\n\n/**\n * Tables this store creates and manages (you run the migrations — see the package README — but\n * these are the fixed set `durableSchema` declares). Feed to your ORM's migration differ\n * exclude/skipTables so it never tries to drop them.\n *\n * ```ts\n * // MikroORM-flavoured example (Drizzle Kit has no built-in equivalent option); adapt to whichever\n * // migration tool generates your diffs.\n * const skipTables = new Set(durableManagedTables());\n * ```\n *\n * Derived from {@link durableSchema} via drizzle-orm's own `getTableName` — one list, so a\n * consumer's denylist can never drift from the table names declared above.\n */\nexport function durableManagedTables(): string[] {\n return Object.values(durableSchema).map((table) => getTableName(table));\n}\n"],"mappings":"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","names":["attributeColumnFor","attributeOperand","normalizeAttributeRows","sqlComparator","and","asc","desc","eq","exists","inArray","isNotNull","isNull","like","lte","or","sql","getTableName","integer","primaryKey","real","sqliteTable","text","workflowRuns","sqliteTable","id","text","primaryKey","workflow","notNull","workflowVersion","status","input","mode","output","error","wakeAt","integer","lockedBy","lockedUntil","awaitingDecisionTaskId","recoveryAttempts","tags","$type","searchAttributes","priority","createdAt","updatedAt","stepCheckpoints","runId","seq","name","kind","stepId","events","attempts","workerGroup","parallelGroup","enqueuedAt","startedAt","finishedAt","t","columns","runAttributes","key","strValue","numValue","real","signalWaiters","token","bufferedSignals","autoIncrement","payload","durableSchema","durableManagedTables","Object","values","map","table","getTableName","DrizzleStateStore","db","createRun","run","insert","workflowRuns","values","toRunRow","reindexAttributes","id","searchAttributes","updateRun","runId","patch","row","toRunPatch","Object","keys","length","update","set","where","eq","attributes","delete","runAttributes","rows","normalizeAttributeRows","getRun","select","from","limit","fromRunRow","deleteRun","stepCheckpoints","signalWaiters","getCheckpoint","seq","and","fromCheckpointRow","saveCheckpoint","checkpoint","toCheckpointRow","onConflictDoUpdate","target","transaction","work","tx","raw","cp","listIncompleteRuns","inArray","status","map","listPendingRuns","orderBy","asc","createdAt","listDueTimers","nowMs","isNotNull","wakeAt","lte","tryLockRun","owner","leaseUntilMs","result","lockedBy","lockedUntil","or","isNull","changes","releaseRunLock","renewRunLock","listRuns","query","filters","workflow","undefined","statuses","sql","tag","like","tags","f","attributeExists","filter","desc","offset","col","attributeColumnFor","numValue","strValue","cmp","sqlComparator","op","exists","one","key","attributeOperand","listCheckpoints","getLatestCheckpointByName","name","listCheckpointsByNamePrefix","prefixes","p","putSignalWaiter","waiter","token","parallelGroup","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","awaitingDecisionTaskId","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","enqueuedAt","startedAt","finishedAt"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dudousxd/nestjs-durable-store-drizzle",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "Drizzle ORM (SQLite/libSQL) adapter for the nestjs-durable StateStore",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Davide Carvalho",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"drizzle-orm": "0.44.7",
|
|
26
26
|
"typescript": "5.9.3",
|
|
27
27
|
"tsup": "8.3.5",
|
|
28
|
-
"@dudousxd/nestjs-durable-core": "^0.
|
|
29
|
-
"@dudousxd/nestjs-durable-testing": "^0.7.
|
|
28
|
+
"@dudousxd/nestjs-durable-core": "^0.50.0",
|
|
29
|
+
"@dudousxd/nestjs-durable-testing": "^0.7.2"
|
|
30
30
|
},
|
|
31
31
|
"module": "./dist/index.js",
|
|
32
32
|
"exports": {
|