@dudousxd/nestjs-durable-store-drizzle 0.10.2 → 0.10.4
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 +23 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +23 -5
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -54,6 +54,9 @@ var workflowRuns = (0, import_sqlite_core.sqliteTable)("durable_workflow_runs",
|
|
|
54
54
|
wakeAt: (0, import_sqlite_core.integer)("wake_at"),
|
|
55
55
|
lockedBy: (0, import_sqlite_core.text)("locked_by"),
|
|
56
56
|
lockedUntil: (0, import_sqlite_core.integer)("locked_until"),
|
|
57
|
+
// REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so
|
|
58
|
+
// only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.
|
|
59
|
+
awaitingDecisionTaskId: (0, import_sqlite_core.text)("awaiting_decision_task_id"),
|
|
57
60
|
recoveryAttempts: (0, import_sqlite_core.integer)("recovery_attempts"),
|
|
58
61
|
tags: (0, import_sqlite_core.text)("tags", {
|
|
59
62
|
mode: "json"
|
|
@@ -117,7 +120,11 @@ var runAttributes = (0, import_sqlite_core.sqliteTable)("durable_run_attributes"
|
|
|
117
120
|
var signalWaiters = (0, import_sqlite_core.sqliteTable)("durable_signal_waiters", {
|
|
118
121
|
token: (0, import_sqlite_core.text)("token").primaryKey(),
|
|
119
122
|
runId: (0, import_sqlite_core.text)("run_id").notNull(),
|
|
120
|
-
seq: (0, import_sqlite_core.integer)("seq").notNull()
|
|
123
|
+
seq: (0, import_sqlite_core.integer)("seq").notNull(),
|
|
124
|
+
// A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the
|
|
125
|
+
// engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the
|
|
126
|
+
// dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.
|
|
127
|
+
parallelGroup: (0, import_sqlite_core.text)("parallel_group")
|
|
121
128
|
});
|
|
122
129
|
var bufferedSignals = (0, import_sqlite_core.sqliteTable)("durable_buffered_signals", {
|
|
123
130
|
id: (0, import_sqlite_core.integer)("id").primaryKey({
|
|
@@ -275,11 +282,17 @@ var DrizzleStateStore = class {
|
|
|
275
282
|
return rows.map(fromCheckpointRow);
|
|
276
283
|
}
|
|
277
284
|
async putSignalWaiter(waiter) {
|
|
278
|
-
await this.db.insert(signalWaiters).values(
|
|
285
|
+
await this.db.insert(signalWaiters).values({
|
|
286
|
+
token: waiter.token,
|
|
287
|
+
runId: waiter.runId,
|
|
288
|
+
seq: waiter.seq,
|
|
289
|
+
parallelGroup: waiter.parallelGroup ?? null
|
|
290
|
+
}).onConflictDoUpdate({
|
|
279
291
|
target: signalWaiters.token,
|
|
280
292
|
set: {
|
|
281
293
|
runId: waiter.runId,
|
|
282
|
-
seq: waiter.seq
|
|
294
|
+
seq: waiter.seq,
|
|
295
|
+
parallelGroup: waiter.parallelGroup ?? null
|
|
283
296
|
}
|
|
284
297
|
});
|
|
285
298
|
}
|
|
@@ -291,7 +304,8 @@ var DrizzleStateStore = class {
|
|
|
291
304
|
return {
|
|
292
305
|
token: row.token,
|
|
293
306
|
runId: row.runId,
|
|
294
|
-
seq: row.seq
|
|
307
|
+
seq: row.seq,
|
|
308
|
+
parallelGroup: row.parallelGroup ?? void 0
|
|
295
309
|
};
|
|
296
310
|
}
|
|
297
311
|
async listSignalWaiters(prefix) {
|
|
@@ -299,7 +313,8 @@ var DrizzleStateStore = class {
|
|
|
299
313
|
return rows.map((r) => ({
|
|
300
314
|
token: r.token,
|
|
301
315
|
runId: r.runId,
|
|
302
|
-
seq: r.seq
|
|
316
|
+
seq: r.seq,
|
|
317
|
+
parallelGroup: r.parallelGroup ?? void 0
|
|
303
318
|
}));
|
|
304
319
|
}
|
|
305
320
|
async bufferSignal(token, payload) {
|
|
@@ -330,6 +345,7 @@ function toRunRow(run) {
|
|
|
330
345
|
wakeAt: run.wakeAt ?? null,
|
|
331
346
|
lockedBy: run.lockedBy ?? null,
|
|
332
347
|
lockedUntil: run.lockedUntil ?? null,
|
|
348
|
+
awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,
|
|
333
349
|
recoveryAttempts: run.recoveryAttempts ?? null,
|
|
334
350
|
tags: run.tags ?? null,
|
|
335
351
|
searchAttributes: run.searchAttributes ?? null,
|
|
@@ -350,6 +366,7 @@ function toRunPatch(patch) {
|
|
|
350
366
|
if ("wakeAt" in patch) row.wakeAt = patch.wakeAt ?? null;
|
|
351
367
|
if ("lockedBy" in patch) row.lockedBy = patch.lockedBy ?? null;
|
|
352
368
|
if ("lockedUntil" in patch) row.lockedUntil = patch.lockedUntil ?? null;
|
|
369
|
+
if ("awaitingDecisionTaskId" in patch) row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;
|
|
353
370
|
if ("recoveryAttempts" in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;
|
|
354
371
|
if ("tags" in patch) row.tags = patch.tags ?? null;
|
|
355
372
|
if ("searchAttributes" in patch) row.searchAttributes = patch.searchAttributes ?? null;
|
|
@@ -371,6 +388,7 @@ function fromRunRow(row) {
|
|
|
371
388
|
wakeAt: row.wakeAt ?? void 0,
|
|
372
389
|
lockedBy: row.lockedBy ?? void 0,
|
|
373
390
|
lockedUntil: row.lockedUntil ?? void 0,
|
|
391
|
+
awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? void 0,
|
|
374
392
|
recoveryAttempts: row.recoveryAttempts ?? void 0,
|
|
375
393
|
tags: row.tags ?? void 0,
|
|
376
394
|
searchAttributes: row.searchAttributes ?? void 0,
|
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(waiter)\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq },\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 { token: row.token, runId: row.runId, seq: row.seq };\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) => ({ token: r.token, runId: r.runId, seq: r.seq }));\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});\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","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","parallelGroup","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 { 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"],"mappings":"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","names":["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","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";
|
|
@@ -791,6 +810,25 @@ declare const signalWaiters: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
791
810
|
identity: undefined;
|
|
792
811
|
generated: undefined;
|
|
793
812
|
}, {}, {}>;
|
|
813
|
+
parallelGroup: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
814
|
+
name: "parallel_group";
|
|
815
|
+
tableName: "durable_signal_waiters";
|
|
816
|
+
dataType: "string";
|
|
817
|
+
columnType: "SQLiteText";
|
|
818
|
+
data: string;
|
|
819
|
+
driverParam: string;
|
|
820
|
+
notNull: false;
|
|
821
|
+
hasDefault: false;
|
|
822
|
+
isPrimaryKey: false;
|
|
823
|
+
isAutoincrement: false;
|
|
824
|
+
hasRuntimeDefault: false;
|
|
825
|
+
enumValues: [string, ...string[]];
|
|
826
|
+
baseColumn: never;
|
|
827
|
+
identity: undefined;
|
|
828
|
+
generated: undefined;
|
|
829
|
+
}, {}, {
|
|
830
|
+
length: number | undefined;
|
|
831
|
+
}>;
|
|
794
832
|
};
|
|
795
833
|
dialect: "sqlite";
|
|
796
834
|
}>;
|
|
@@ -1039,6 +1077,25 @@ declare const durableSchema: {
|
|
|
1039
1077
|
identity: undefined;
|
|
1040
1078
|
generated: undefined;
|
|
1041
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
|
+
}>;
|
|
1042
1099
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1043
1100
|
name: "recovery_attempts";
|
|
1044
1101
|
tableName: "durable_workflow_runs";
|
|
@@ -1598,6 +1655,25 @@ declare const durableSchema: {
|
|
|
1598
1655
|
identity: undefined;
|
|
1599
1656
|
generated: undefined;
|
|
1600
1657
|
}, {}, {}>;
|
|
1658
|
+
parallelGroup: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1659
|
+
name: "parallel_group";
|
|
1660
|
+
tableName: "durable_signal_waiters";
|
|
1661
|
+
dataType: "string";
|
|
1662
|
+
columnType: "SQLiteText";
|
|
1663
|
+
data: string;
|
|
1664
|
+
driverParam: string;
|
|
1665
|
+
notNull: false;
|
|
1666
|
+
hasDefault: false;
|
|
1667
|
+
isPrimaryKey: false;
|
|
1668
|
+
isAutoincrement: false;
|
|
1669
|
+
hasRuntimeDefault: false;
|
|
1670
|
+
enumValues: [string, ...string[]];
|
|
1671
|
+
baseColumn: never;
|
|
1672
|
+
identity: undefined;
|
|
1673
|
+
generated: undefined;
|
|
1674
|
+
}, {}, {
|
|
1675
|
+
length: number | undefined;
|
|
1676
|
+
}>;
|
|
1601
1677
|
};
|
|
1602
1678
|
dialect: "sqlite";
|
|
1603
1679
|
}>;
|
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";
|
|
@@ -791,6 +810,25 @@ declare const signalWaiters: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
791
810
|
identity: undefined;
|
|
792
811
|
generated: undefined;
|
|
793
812
|
}, {}, {}>;
|
|
813
|
+
parallelGroup: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
814
|
+
name: "parallel_group";
|
|
815
|
+
tableName: "durable_signal_waiters";
|
|
816
|
+
dataType: "string";
|
|
817
|
+
columnType: "SQLiteText";
|
|
818
|
+
data: string;
|
|
819
|
+
driverParam: string;
|
|
820
|
+
notNull: false;
|
|
821
|
+
hasDefault: false;
|
|
822
|
+
isPrimaryKey: false;
|
|
823
|
+
isAutoincrement: false;
|
|
824
|
+
hasRuntimeDefault: false;
|
|
825
|
+
enumValues: [string, ...string[]];
|
|
826
|
+
baseColumn: never;
|
|
827
|
+
identity: undefined;
|
|
828
|
+
generated: undefined;
|
|
829
|
+
}, {}, {
|
|
830
|
+
length: number | undefined;
|
|
831
|
+
}>;
|
|
794
832
|
};
|
|
795
833
|
dialect: "sqlite";
|
|
796
834
|
}>;
|
|
@@ -1039,6 +1077,25 @@ declare const durableSchema: {
|
|
|
1039
1077
|
identity: undefined;
|
|
1040
1078
|
generated: undefined;
|
|
1041
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
|
+
}>;
|
|
1042
1099
|
recoveryAttempts: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1043
1100
|
name: "recovery_attempts";
|
|
1044
1101
|
tableName: "durable_workflow_runs";
|
|
@@ -1598,6 +1655,25 @@ declare const durableSchema: {
|
|
|
1598
1655
|
identity: undefined;
|
|
1599
1656
|
generated: undefined;
|
|
1600
1657
|
}, {}, {}>;
|
|
1658
|
+
parallelGroup: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1659
|
+
name: "parallel_group";
|
|
1660
|
+
tableName: "durable_signal_waiters";
|
|
1661
|
+
dataType: "string";
|
|
1662
|
+
columnType: "SQLiteText";
|
|
1663
|
+
data: string;
|
|
1664
|
+
driverParam: string;
|
|
1665
|
+
notNull: false;
|
|
1666
|
+
hasDefault: false;
|
|
1667
|
+
isPrimaryKey: false;
|
|
1668
|
+
isAutoincrement: false;
|
|
1669
|
+
hasRuntimeDefault: false;
|
|
1670
|
+
enumValues: [string, ...string[]];
|
|
1671
|
+
baseColumn: never;
|
|
1672
|
+
identity: undefined;
|
|
1673
|
+
generated: undefined;
|
|
1674
|
+
}, {}, {
|
|
1675
|
+
length: number | undefined;
|
|
1676
|
+
}>;
|
|
1601
1677
|
};
|
|
1602
1678
|
dialect: "sqlite";
|
|
1603
1679
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,9 @@ var workflowRuns = sqliteTable("durable_workflow_runs", {
|
|
|
24
24
|
wakeAt: integer("wake_at"),
|
|
25
25
|
lockedBy: text("locked_by"),
|
|
26
26
|
lockedUntil: integer("locked_until"),
|
|
27
|
+
// REMOTE turn the engine suspended on awaiting a decision; matched by completeRemoteDecision so
|
|
28
|
+
// only the currently-awaited turn's decision is applied. Nullable: cleared when a decision lands.
|
|
29
|
+
awaitingDecisionTaskId: text("awaiting_decision_task_id"),
|
|
27
30
|
recoveryAttempts: integer("recovery_attempts"),
|
|
28
31
|
tags: text("tags", {
|
|
29
32
|
mode: "json"
|
|
@@ -87,7 +90,11 @@ var runAttributes = sqliteTable("durable_run_attributes", {
|
|
|
87
90
|
var signalWaiters = sqliteTable("durable_signal_waiters", {
|
|
88
91
|
token: text("token").primaryKey(),
|
|
89
92
|
runId: text("run_id").notNull(),
|
|
90
|
-
seq: integer("seq").notNull()
|
|
93
|
+
seq: integer("seq").notNull(),
|
|
94
|
+
// A ctx.gather_children/ctx.all child fan-out tags every awaited child with the same group; the
|
|
95
|
+
// engine threads it onto the waiter so the resolving `signal:child:` checkpoint carries it and the
|
|
96
|
+
// dashboard renders the fan as one parallel group. Nullable: only fan-out child waiters carry it.
|
|
97
|
+
parallelGroup: text("parallel_group")
|
|
91
98
|
});
|
|
92
99
|
var bufferedSignals = sqliteTable("durable_buffered_signals", {
|
|
93
100
|
id: integer("id").primaryKey({
|
|
@@ -245,11 +252,17 @@ var DrizzleStateStore = class {
|
|
|
245
252
|
return rows.map(fromCheckpointRow);
|
|
246
253
|
}
|
|
247
254
|
async putSignalWaiter(waiter) {
|
|
248
|
-
await this.db.insert(signalWaiters).values(
|
|
255
|
+
await this.db.insert(signalWaiters).values({
|
|
256
|
+
token: waiter.token,
|
|
257
|
+
runId: waiter.runId,
|
|
258
|
+
seq: waiter.seq,
|
|
259
|
+
parallelGroup: waiter.parallelGroup ?? null
|
|
260
|
+
}).onConflictDoUpdate({
|
|
249
261
|
target: signalWaiters.token,
|
|
250
262
|
set: {
|
|
251
263
|
runId: waiter.runId,
|
|
252
|
-
seq: waiter.seq
|
|
264
|
+
seq: waiter.seq,
|
|
265
|
+
parallelGroup: waiter.parallelGroup ?? null
|
|
253
266
|
}
|
|
254
267
|
});
|
|
255
268
|
}
|
|
@@ -261,7 +274,8 @@ var DrizzleStateStore = class {
|
|
|
261
274
|
return {
|
|
262
275
|
token: row.token,
|
|
263
276
|
runId: row.runId,
|
|
264
|
-
seq: row.seq
|
|
277
|
+
seq: row.seq,
|
|
278
|
+
parallelGroup: row.parallelGroup ?? void 0
|
|
265
279
|
};
|
|
266
280
|
}
|
|
267
281
|
async listSignalWaiters(prefix) {
|
|
@@ -269,7 +283,8 @@ var DrizzleStateStore = class {
|
|
|
269
283
|
return rows.map((r) => ({
|
|
270
284
|
token: r.token,
|
|
271
285
|
runId: r.runId,
|
|
272
|
-
seq: r.seq
|
|
286
|
+
seq: r.seq,
|
|
287
|
+
parallelGroup: r.parallelGroup ?? void 0
|
|
273
288
|
}));
|
|
274
289
|
}
|
|
275
290
|
async bufferSignal(token, payload) {
|
|
@@ -300,6 +315,7 @@ function toRunRow(run) {
|
|
|
300
315
|
wakeAt: run.wakeAt ?? null,
|
|
301
316
|
lockedBy: run.lockedBy ?? null,
|
|
302
317
|
lockedUntil: run.lockedUntil ?? null,
|
|
318
|
+
awaitingDecisionTaskId: run.awaitingDecisionTaskId ?? null,
|
|
303
319
|
recoveryAttempts: run.recoveryAttempts ?? null,
|
|
304
320
|
tags: run.tags ?? null,
|
|
305
321
|
searchAttributes: run.searchAttributes ?? null,
|
|
@@ -320,6 +336,7 @@ function toRunPatch(patch) {
|
|
|
320
336
|
if ("wakeAt" in patch) row.wakeAt = patch.wakeAt ?? null;
|
|
321
337
|
if ("lockedBy" in patch) row.lockedBy = patch.lockedBy ?? null;
|
|
322
338
|
if ("lockedUntil" in patch) row.lockedUntil = patch.lockedUntil ?? null;
|
|
339
|
+
if ("awaitingDecisionTaskId" in patch) row.awaitingDecisionTaskId = patch.awaitingDecisionTaskId ?? null;
|
|
323
340
|
if ("recoveryAttempts" in patch) row.recoveryAttempts = patch.recoveryAttempts ?? null;
|
|
324
341
|
if ("tags" in patch) row.tags = patch.tags ?? null;
|
|
325
342
|
if ("searchAttributes" in patch) row.searchAttributes = patch.searchAttributes ?? null;
|
|
@@ -341,6 +358,7 @@ function fromRunRow(row) {
|
|
|
341
358
|
wakeAt: row.wakeAt ?? void 0,
|
|
342
359
|
lockedBy: row.lockedBy ?? void 0,
|
|
343
360
|
lockedUntil: row.lockedUntil ?? void 0,
|
|
361
|
+
awaitingDecisionTaskId: row.awaitingDecisionTaskId ?? void 0,
|
|
344
362
|
recoveryAttempts: row.recoveryAttempts ?? void 0,
|
|
345
363
|
tags: row.tags ?? void 0,
|
|
346
364
|
searchAttributes: row.searchAttributes ?? void 0,
|
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(waiter)\n .onConflictDoUpdate({\n target: signalWaiters.token,\n set: { runId: waiter.runId, seq: waiter.seq },\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 { token: row.token, runId: row.runId, seq: row.seq };\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) => ({ token: r.token, runId: r.runId, seq: r.seq }));\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});\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","takeSignalWaiter","listSignalWaiters","prefix","r","bufferSignal","payload","bufferedSignals","takeBufferedSignal","workflowVersion","input","output","error","recoveryAttempts","priority","getTime","updatedAt","Date","kind","stepId","events","attempts","workerGroup","parallelGroup","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 { 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"],"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","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","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","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.4",
|
|
4
4
|
"description": "Drizzle ORM (SQLite/libSQL) adapter for the nestjs-durable StateStore",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Davide Carvalho",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/better-sqlite3": "7.6.11",
|
|
24
|
-
"better-sqlite3": "
|
|
24
|
+
"better-sqlite3": "12.10.0",
|
|
25
25
|
"drizzle-orm": "0.44.7",
|
|
26
26
|
"typescript": "5.9.3",
|
|
27
27
|
"tsup": "8.3.5",
|
|
28
|
-
"@dudousxd/nestjs-durable-
|
|
29
|
-
"@dudousxd/nestjs-durable-
|
|
28
|
+
"@dudousxd/nestjs-durable-core": "^0.44.0",
|
|
29
|
+
"@dudousxd/nestjs-durable-testing": "^0.7.2"
|
|
30
30
|
},
|
|
31
31
|
"module": "./dist/index.js",
|
|
32
32
|
"exports": {
|