@bratsos/workflow-engine 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -12
- package/dist/{chunk-RZY5YRGL.js → chunk-2HEV5ZJL.js} +2 -2
- package/dist/chunk-2HEV5ZJL.js.map +1 -0
- package/dist/{chunk-WQPZ6KON.js → chunk-5C7LRNM7.js} +280 -93
- package/dist/chunk-5C7LRNM7.js.map +1 -0
- package/dist/{chunk-PHLNTR5Z.js → chunk-Q2XDO3UF.js} +28 -7
- package/dist/chunk-Q2XDO3UF.js.map +1 -0
- package/dist/{chunk-ZYMT2PAO.js → chunk-WWK2SPN7.js} +16 -37
- package/dist/chunk-WWK2SPN7.js.map +1 -0
- package/dist/{client-oLD5ilXp.d.ts → client-DYs5wlHp.d.ts} +17 -99
- package/dist/client.d.ts +4 -3
- package/dist/client.js +1 -1
- package/dist/events-D_P24UaY.d.ts +105 -0
- package/dist/{index-CVkkGnxx.d.ts → index-aNuJ2QgN.d.ts} +11 -1
- package/dist/index.d.ts +184 -32
- package/dist/index.js +41 -9
- package/dist/index.js.map +1 -1
- package/dist/{interface-TsryH4d7.d.ts → interface-BeEPzTFy.d.ts} +9 -3
- package/dist/kernel/index.d.ts +6 -5
- package/dist/kernel/index.js +2 -1
- package/dist/kernel/testing/index.d.ts +3 -2
- package/dist/persistence/index.d.ts +2 -2
- package/dist/persistence/index.js +2 -2
- package/dist/persistence/prisma/index.d.ts +2 -2
- package/dist/persistence/prisma/index.js +2 -2
- package/dist/{plugins-C94AT8Wr.d.ts → plugins-Cl0WVVrE.d.ts} +9 -6
- package/dist/{ports-855bktyD.d.ts → ports-swhiWFw4.d.ts} +5 -106
- package/dist/{stage-BPw7m9Wx.d.ts → stage-_7BKqqUG.d.ts} +2 -2
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.js +25 -6
- package/dist/testing/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/workflow-engine/SKILL.md +30 -11
- package/skills/workflow-engine/references/02-workflow-builder.md +2 -0
- package/skills/workflow-engine/references/03-runtime-setup.md +1 -1
- package/skills/workflow-engine/references/08-common-patterns.md +2 -1
- package/skills/workflow-engine/references/09-troubleshooting.md +4 -3
- package/dist/chunk-PHLNTR5Z.js.map +0 -1
- package/dist/chunk-RZY5YRGL.js.map +0 -1
- package/dist/chunk-WQPZ6KON.js.map +0 -1
- package/dist/chunk-ZYMT2PAO.js.map +0 -1
package/dist/testing/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StaleVersionError } from '../chunk-
|
|
1
|
+
import { StaleVersionError } from '../chunk-2HEV5ZJL.js';
|
|
2
2
|
import { randomUUID } from 'crypto';
|
|
3
3
|
|
|
4
4
|
var InMemoryAICallLogger = class {
|
|
@@ -198,7 +198,7 @@ var InMemoryJobQueue = class {
|
|
|
198
198
|
lockedAt: null,
|
|
199
199
|
startedAt: null,
|
|
200
200
|
completedAt: null,
|
|
201
|
-
attempt:
|
|
201
|
+
attempt: 0,
|
|
202
202
|
maxAttempts: this.defaultMaxAttempts,
|
|
203
203
|
lastError: null,
|
|
204
204
|
nextPollAt: options.scheduledFor ?? null,
|
|
@@ -229,13 +229,15 @@ var InMemoryJobQueue = class {
|
|
|
229
229
|
return null;
|
|
230
230
|
}
|
|
231
231
|
const job = pendingJobs[0];
|
|
232
|
+
const newAttempt = job.attempt + 1;
|
|
232
233
|
const updated = {
|
|
233
234
|
...job,
|
|
234
235
|
status: "RUNNING",
|
|
235
236
|
workerId: this.workerId,
|
|
236
237
|
lockedAt: now,
|
|
237
238
|
startedAt: now,
|
|
238
|
-
updatedAt: now
|
|
239
|
+
updatedAt: now,
|
|
240
|
+
attempt: newAttempt
|
|
239
241
|
};
|
|
240
242
|
this.jobs.set(job.id, updated);
|
|
241
243
|
return {
|
|
@@ -244,7 +246,7 @@ var InMemoryJobQueue = class {
|
|
|
244
246
|
workflowId: job.workflowId,
|
|
245
247
|
stageId: job.stageId,
|
|
246
248
|
priority: job.priority,
|
|
247
|
-
attempt:
|
|
249
|
+
attempt: newAttempt,
|
|
248
250
|
maxAttempts: job.maxAttempts,
|
|
249
251
|
payload: job.payload
|
|
250
252
|
};
|
|
@@ -288,7 +290,6 @@ var InMemoryJobQueue = class {
|
|
|
288
290
|
const updated = {
|
|
289
291
|
...job,
|
|
290
292
|
status: "PENDING",
|
|
291
|
-
attempt: job.attempt + 1,
|
|
292
293
|
lastError: error,
|
|
293
294
|
workerId: null,
|
|
294
295
|
lockedAt: null,
|
|
@@ -335,6 +336,23 @@ var InMemoryJobQueue = class {
|
|
|
335
336
|
}
|
|
336
337
|
return released;
|
|
337
338
|
}
|
|
339
|
+
async cancelByRun(workflowRunId) {
|
|
340
|
+
const now = /* @__PURE__ */ new Date();
|
|
341
|
+
let count = 0;
|
|
342
|
+
for (const job of this.jobs.values()) {
|
|
343
|
+
if (job.workflowRunId === workflowRunId && (job.status === "PENDING" || job.status === "SUSPENDED")) {
|
|
344
|
+
const updated = {
|
|
345
|
+
...job,
|
|
346
|
+
status: "CANCELLED",
|
|
347
|
+
completedAt: now,
|
|
348
|
+
updatedAt: now
|
|
349
|
+
};
|
|
350
|
+
this.jobs.set(job.id, updated);
|
|
351
|
+
count++;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return count;
|
|
355
|
+
}
|
|
338
356
|
// ============================================================================
|
|
339
357
|
// Test Helpers
|
|
340
358
|
// ============================================================================
|
|
@@ -469,7 +487,8 @@ var InMemoryWorkflowPersistence = class {
|
|
|
469
487
|
config: data.config ?? {},
|
|
470
488
|
totalCost: 0,
|
|
471
489
|
totalTokens: 0,
|
|
472
|
-
priority: data.priority ?? 5
|
|
490
|
+
priority: data.priority ?? 5,
|
|
491
|
+
metadata: data.metadata ?? null
|
|
473
492
|
};
|
|
474
493
|
this.runs.set(record.id, record);
|
|
475
494
|
return { ...record };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 1,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: job.attempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING with incremented attempt\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n attempt: job.attempt + 1,\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/testing/in-memory-ai-logger.ts","../../src/testing/in-memory-job-queue.ts","../../src/testing/in-memory-persistence.ts"],"names":["randomUUID"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * In-Memory AI Call Logger\n *\n * A complete in-memory implementation of AICallLogger for testing.\n * Tracks all AI calls with full cost/token tracking and topic-based aggregation.\n *\n * @example\n * ```typescript\n * import { InMemoryAICallLogger } from '@bratsos/workflow-engine/testing';\n *\n * const aiLogger = new InMemoryAICallLogger();\n * // Use in tests...\n * aiLogger.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n AICallLogger,\n AICallRecord,\n AIHelperStats,\n CreateAICallInput,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryAICallLogger implements AICallLogger {\n private calls = new Map<string, AICallRecord>();\n private recordedBatches = new Set<string>();\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n /**\n * Log a single AI call (fire and forget)\n */\n logCall(call: CreateAICallInput): void {\n const id = randomUUID();\n const record: AICallRecord = {\n id,\n createdAt: new Date(),\n topic: call.topic,\n callType: call.callType,\n modelKey: call.modelKey,\n modelId: call.modelId,\n prompt: call.prompt,\n response: call.response,\n inputTokens: call.inputTokens,\n outputTokens: call.outputTokens,\n cost: call.cost,\n metadata: call.metadata ?? null,\n };\n this.calls.set(id, record);\n }\n\n /**\n * Log batch results (for recording batch API results)\n */\n async logBatchResults(\n batchId: string,\n results: CreateAICallInput[],\n ): Promise<void> {\n // Mark batch as recorded\n this.recordedBatches.add(batchId);\n\n // Log each result\n for (const result of results) {\n this.logCall({\n ...result,\n metadata: {\n ...(result.metadata as Record<string, unknown> | undefined),\n batchId,\n },\n });\n }\n }\n\n /**\n * Get aggregated stats for a topic prefix\n */\n async getStats(topicPrefix: string): Promise<AIHelperStats> {\n const matchingCalls = Array.from(this.calls.values()).filter((call) =>\n call.topic.startsWith(topicPrefix),\n );\n\n const stats: AIHelperStats = {\n totalCalls: matchingCalls.length,\n totalInputTokens: 0,\n totalOutputTokens: 0,\n totalCost: 0,\n perModel: {},\n };\n\n for (const call of matchingCalls) {\n stats.totalInputTokens += call.inputTokens;\n stats.totalOutputTokens += call.outputTokens;\n stats.totalCost += call.cost;\n\n // Aggregate per model\n if (!stats.perModel[call.modelKey]) {\n stats.perModel[call.modelKey] = {\n calls: 0,\n inputTokens: 0,\n outputTokens: 0,\n cost: 0,\n };\n }\n stats.perModel[call.modelKey]!.calls++;\n stats.perModel[call.modelKey]!.inputTokens += call.inputTokens;\n stats.perModel[call.modelKey]!.outputTokens += call.outputTokens;\n stats.perModel[call.modelKey]!.cost += call.cost;\n }\n\n return stats;\n }\n\n /**\n * Check if batch results are already recorded\n */\n async isRecorded(batchId: string): Promise<boolean> {\n return this.recordedBatches.has(batchId);\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.calls.clear();\n this.recordedBatches.clear();\n }\n\n /**\n * Get all calls for inspection\n */\n getAllCalls(): AICallRecord[] {\n return Array.from(this.calls.values()).map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic for inspection\n */\n getCallsByTopic(topic: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic === topic)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by topic prefix for inspection\n */\n getCallsByTopicPrefix(prefix: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.topic.startsWith(prefix))\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by model for inspection\n */\n getCallsByModel(modelKey: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.modelKey === modelKey)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get calls by call type for inspection\n */\n getCallsByType(callType: string): AICallRecord[] {\n return Array.from(this.calls.values())\n .filter((c) => c.callType === callType)\n .map((c) => ({ ...c }));\n }\n\n /**\n * Get total cost across all calls\n */\n getTotalCost(): number {\n let total = 0;\n for (const call of this.calls.values()) {\n total += call.cost;\n }\n return total;\n }\n\n /**\n * Get total tokens across all calls\n */\n getTotalTokens(): { input: number; output: number } {\n let input = 0;\n let output = 0;\n for (const call of this.calls.values()) {\n input += call.inputTokens;\n output += call.outputTokens;\n }\n return { input, output };\n }\n\n /**\n * Get call count\n */\n getCallCount(): number {\n return this.calls.size;\n }\n\n /**\n * Get all recorded batch IDs\n */\n getRecordedBatchIds(): string[] {\n return Array.from(this.recordedBatches);\n }\n\n /**\n * Get the last call made (useful for assertions)\n */\n getLastCall(): AICallRecord | null {\n const calls = Array.from(this.calls.values());\n if (calls.length === 0) return null;\n\n // Sort by createdAt descending\n calls.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n return { ...calls[0]! };\n }\n\n /**\n * Assert a call was made with specific properties\n */\n hasCallMatching(predicate: (call: AICallRecord) => boolean): boolean {\n return Array.from(this.calls.values()).some(predicate);\n }\n}\n","/**\n * In-Memory Job Queue\n *\n * A complete in-memory implementation of JobQueue for testing.\n * Supports priority ordering, locking, and stale job recovery.\n *\n * @example\n * ```typescript\n * import { InMemoryJobQueue } from '@bratsos/workflow-engine/testing';\n *\n * const jobQueue = new InMemoryJobQueue();\n * // Use in tests...\n * jobQueue.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport type {\n DequeueResult,\n EnqueueJobInput,\n JobQueue,\n JobRecord,\n JobStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryJobQueue implements JobQueue {\n private jobs = new Map<string, JobRecord>();\n private workerId: string;\n private defaultMaxAttempts = 3;\n\n constructor(workerId?: string) {\n this.workerId = workerId ?? `worker-${randomUUID().slice(0, 8)}`;\n }\n\n // ============================================================================\n // Core Operations\n // ============================================================================\n\n async enqueue(options: EnqueueJobInput): Promise<string> {\n const now = new Date();\n const id = randomUUID();\n\n const job: JobRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n workflowRunId: options.workflowRunId,\n workflowId: options.workflowId,\n stageId: options.stageId,\n status: \"PENDING\",\n priority: options.priority ?? 5,\n workerId: null,\n lockedAt: null,\n startedAt: null,\n completedAt: null,\n attempt: 0,\n maxAttempts: this.defaultMaxAttempts,\n lastError: null,\n nextPollAt: options.scheduledFor ?? null,\n payload: options.payload ?? {},\n };\n\n this.jobs.set(id, job);\n return id;\n }\n\n async enqueueParallel(jobs: EnqueueJobInput[]): Promise<string[]> {\n const ids: string[] = [];\n for (const job of jobs) {\n const id = await this.enqueue(job);\n ids.push(id);\n }\n return ids;\n }\n\n async dequeue(): Promise<DequeueResult | null> {\n // Find the highest priority PENDING job\n const now = new Date();\n const pendingJobs = Array.from(this.jobs.values())\n .filter(\n (j) =>\n j.status === \"PENDING\" &&\n (j.nextPollAt === null || j.nextPollAt <= now),\n )\n .sort((a, b) => {\n // Higher priority first\n if (b.priority !== a.priority) {\n return b.priority - a.priority;\n }\n // Earlier creation first (FIFO for same priority)\n return a.createdAt.getTime() - b.createdAt.getTime();\n });\n\n if (pendingJobs.length === 0) {\n return null;\n }\n\n const job = pendingJobs[0]!;\n\n // Lock the job and increment attempt (matches Prisma dequeue semantics)\n const newAttempt = job.attempt + 1;\n const updated: JobRecord = {\n ...job,\n status: \"RUNNING\",\n workerId: this.workerId,\n lockedAt: now,\n startedAt: now,\n updatedAt: now,\n attempt: newAttempt,\n };\n this.jobs.set(job.id, updated);\n\n return {\n jobId: job.id,\n workflowRunId: job.workflowRunId,\n workflowId: job.workflowId,\n stageId: job.stageId,\n priority: job.priority,\n attempt: newAttempt,\n maxAttempts: job.maxAttempts,\n payload: job.payload,\n };\n }\n\n async complete(jobId: string): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n const updated: JobRecord = {\n ...job,\n status: \"COMPLETED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n\n async suspend(jobId: string, nextPollAt: Date): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const updated: JobRecord = {\n ...job,\n status: \"SUSPENDED\",\n nextPollAt,\n workerId: null,\n lockedAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n\n async fail(\n jobId: string,\n error: string,\n shouldRetry: boolean = true,\n ): Promise<void> {\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job not found: ${jobId}`);\n }\n\n const now = new Date();\n\n if (shouldRetry && job.attempt < job.maxAttempts) {\n // Retry: move back to PENDING (attempt was already incremented during dequeue)\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n lastError: error,\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n } else {\n // No more retries: mark as FAILED\n const updated: JobRecord = {\n ...job,\n status: \"FAILED\",\n lastError: error,\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n async getSuspendedJobsReadyToPoll(): Promise<\n Array<{ jobId: string; stageId: string; workflowRunId: string }>\n > {\n const now = new Date();\n return Array.from(this.jobs.values())\n .filter(\n (j) => j.status === \"SUSPENDED\" && j.nextPollAt && j.nextPollAt <= now,\n )\n .map((j) => ({\n jobId: j.id,\n stageId: j.stageId,\n workflowRunId: j.workflowRunId,\n }));\n }\n\n async releaseStaleJobs(staleThresholdMs: number = 60000): Promise<number> {\n const now = new Date();\n const threshold = new Date(now.getTime() - staleThresholdMs);\n let released = 0;\n\n for (const job of this.jobs.values()) {\n if (\n job.status === \"RUNNING\" &&\n job.lockedAt &&\n job.lockedAt < threshold\n ) {\n // Release the stale lock\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n workerId: null,\n lockedAt: null,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n released++;\n }\n }\n\n return released;\n }\n\n async cancelByRun(workflowRunId: string): Promise<number> {\n const now = new Date();\n let count = 0;\n for (const job of this.jobs.values()) {\n if (\n job.workflowRunId === workflowRunId &&\n (job.status === \"PENDING\" || job.status === \"SUSPENDED\")\n ) {\n const updated: JobRecord = {\n ...job,\n status: \"CANCELLED\",\n completedAt: now,\n updatedAt: now,\n };\n this.jobs.set(job.id, updated);\n count++;\n }\n }\n return count;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all jobs - useful between tests\n */\n clear(): void {\n this.jobs.clear();\n }\n\n /**\n * Get all jobs for inspection\n */\n getAllJobs(): JobRecord[] {\n return Array.from(this.jobs.values()).map((j) => ({ ...j }));\n }\n\n /**\n * Get jobs by status for inspection\n */\n getJobsByStatus(status: JobStatus): JobRecord[] {\n return Array.from(this.jobs.values())\n .filter((j) => j.status === status)\n .map((j) => ({ ...j }));\n }\n\n /**\n * Get a specific job by ID\n */\n getJob(jobId: string): JobRecord | null {\n const job = this.jobs.get(jobId);\n return job ? { ...job } : null;\n }\n\n /**\n * Get the worker ID for this queue instance\n */\n getWorkerId(): string {\n return this.workerId;\n }\n\n /**\n * Set max attempts for new jobs\n */\n setDefaultMaxAttempts(maxAttempts: number): void {\n this.defaultMaxAttempts = maxAttempts;\n }\n\n /**\n * Simulate a worker crash by releasing a job's lock without completing it\n */\n simulateCrash(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"RUNNING\") {\n // Don't change status - just leave it locked by the \"crashed\" worker\n // releaseStaleJobs() will clean it up\n }\n }\n\n /**\n * Move a suspended job back to pending (for manual resume testing)\n */\n resumeJob(jobId: string): void {\n const job = this.jobs.get(jobId);\n if (job && job.status === \"SUSPENDED\") {\n const updated: JobRecord = {\n ...job,\n status: \"PENDING\",\n nextPollAt: null,\n updatedAt: new Date(),\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set lockedAt for testing stale job scenarios\n */\n setJobLockedAt(jobId: string, lockedAt: Date): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n lockedAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n\n /**\n * Set nextPollAt for testing suspended job polling\n */\n setJobNextPollAt(jobId: string, nextPollAt: Date | null): void {\n const job = this.jobs.get(jobId);\n if (job) {\n const updated: JobRecord = {\n ...job,\n nextPollAt,\n };\n this.jobs.set(jobId, updated);\n }\n }\n}\n","/**\n * In-Memory Workflow Persistence\n *\n * A complete in-memory implementation of WorkflowPersistence for testing.\n * All data is stored in Maps and lost when the instance is garbage collected.\n *\n * @example\n * ```typescript\n * import { InMemoryWorkflowPersistence } from '@bratsos/workflow-engine/testing';\n *\n * const persistence = new InMemoryWorkflowPersistence();\n * // Use in tests...\n * persistence.clear(); // Reset between tests\n * ```\n */\n\nimport { randomUUID } from \"crypto\";\nimport {\n type CreateLogInput,\n type CreateOutboxEventInput,\n type CreateRunInput,\n type CreateStageInput,\n type IdempotencyRecord,\n type OutboxRecord,\n type SaveArtifactInput,\n StaleVersionError,\n type UpdateRunInput,\n type UpdateStageInput,\n type UpsertStageInput,\n type WorkflowArtifactRecord,\n type WorkflowLogRecord,\n type WorkflowPersistence,\n type WorkflowRunRecord,\n type WorkflowStageRecord,\n type WorkflowStageStatus,\n type WorkflowStatus,\n} from \"../persistence/interface.js\";\n\nexport class InMemoryWorkflowPersistence implements WorkflowPersistence {\n private runs = new Map<string, WorkflowRunRecord>();\n private stages = new Map<string, WorkflowStageRecord>();\n private logs = new Map<string, WorkflowLogRecord>();\n private artifacts = new Map<string, WorkflowArtifactRecord>();\n private outbox: OutboxRecord[] = [];\n private idempotencyKeys = new Map<string, IdempotencyRecord>();\n private idempotencyInProgress = new Set<string>();\n private outboxSequences = new Map<string, number>();\n\n // Helper to generate composite keys for stages\n private stageKey(runId: string, stageId: string): string {\n return `${runId}:${stageId}`;\n }\n\n // Helper to generate composite keys for artifacts\n private artifactKey(runId: string, key: string): string {\n return `${runId}:${key}`;\n }\n\n private idempotencyCompositeKey(commandType: string, key: string): string {\n return `${commandType}:${key}`;\n }\n\n async withTransaction<T>(\n fn: (tx: WorkflowPersistence) => Promise<T>,\n ): Promise<T> {\n return fn(this);\n }\n\n // ============================================================================\n // WorkflowRun Operations\n // ============================================================================\n\n async createRun(data: CreateRunInput): Promise<WorkflowRunRecord> {\n const now = new Date();\n const record: WorkflowRunRecord = {\n id: data.id ?? randomUUID(),\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowId: data.workflowId,\n workflowName: data.workflowName,\n workflowType: data.workflowType,\n status: \"PENDING\",\n startedAt: null,\n completedAt: null,\n duration: null,\n input: data.input,\n output: null,\n config: data.config ?? {},\n totalCost: 0,\n totalTokens: 0,\n priority: data.priority ?? 5,\n metadata: data.metadata ?? null,\n };\n this.runs.set(record.id, record);\n return { ...record };\n }\n\n async updateRun(id: string, data: UpdateRunInput): Promise<void> {\n const run = this.runs.get(id);\n if (!run) {\n throw new Error(`WorkflowRun not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n run.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowRun\",\n id,\n data.expectedVersion,\n run.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowRunRecord = {\n ...run,\n ...rest,\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n }\n\n async getRun(id: string): Promise<WorkflowRunRecord | null> {\n const run = this.runs.get(id);\n return run ? { ...run } : null;\n }\n\n async getRunStatus(id: string): Promise<WorkflowStatus | null> {\n const run = this.runs.get(id);\n return run?.status ?? null;\n }\n\n async getRunsByStatus(status: WorkflowStatus): Promise<WorkflowRunRecord[]> {\n return Array.from(this.runs.values())\n .filter((run) => run.status === status)\n .map((run) => ({ ...run }));\n }\n\n async getStuckRuns(stuckSince: Date): Promise<WorkflowRunRecord[]> {\n const runningRuns = await this.getRunsByStatus(\"RUNNING\");\n return runningRuns.filter((run) => {\n // Find all stages for this run (deduplicate by ID since stages are stored with composite keys)\n const seenIds = new Set<string>();\n const stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== run.id) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n const lastStageUpdate = stages.reduce(\n (max, s) => (s.updatedAt > max ? s.updatedAt : max),\n new Date(0),\n );\n const lastActivity =\n run.updatedAt > lastStageUpdate ? run.updatedAt : lastStageUpdate;\n return lastActivity <= stuckSince;\n });\n }\n\n async claimPendingRun(id: string): Promise<boolean> {\n const run = this.runs.get(id);\n if (!run || run.status !== \"PENDING\") {\n return false;\n }\n\n // Atomically update status to RUNNING\n const updated: WorkflowRunRecord = {\n ...run,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: run.version + 1,\n };\n this.runs.set(id, updated);\n return true;\n }\n\n async claimNextPendingRun(): Promise<WorkflowRunRecord | null> {\n // Find all pending runs\n const pendingRuns = Array.from(this.runs.values())\n .filter((run) => run.status === \"PENDING\")\n // Sort by priority (highest first), then by createdAt (oldest first - FIFO)\n .sort((a, b) => {\n if (a.priority !== b.priority) {\n return b.priority - a.priority; // Higher priority first\n }\n return a.createdAt.getTime() - b.createdAt.getTime(); // Oldest first\n });\n\n if (pendingRuns.length === 0) {\n return null;\n }\n\n // Get the first one and atomically claim it\n const runToClaim = pendingRuns[0];\n\n // Double-check it's still pending (simulates FOR UPDATE SKIP LOCKED behavior)\n const currentRun = this.runs.get(runToClaim.id);\n if (!currentRun || currentRun.status !== \"PENDING\") {\n // Another worker claimed it between our query and now\n // In real FOR UPDATE SKIP LOCKED, this row would be skipped\n // Try the next one recursively\n return this.claimNextPendingRun();\n }\n\n // Atomically update status to RUNNING\n const claimed: WorkflowRunRecord = {\n ...currentRun,\n status: \"RUNNING\",\n startedAt: new Date(),\n updatedAt: new Date(),\n version: currentRun.version + 1,\n };\n this.runs.set(claimed.id, claimed);\n\n return { ...claimed };\n }\n\n // ============================================================================\n // WorkflowStage Operations\n // ============================================================================\n\n async createStage(data: CreateStageInput): Promise<WorkflowStageRecord> {\n const now = new Date();\n const id = randomUUID();\n const record: WorkflowStageRecord = {\n id,\n createdAt: now,\n updatedAt: now,\n version: 1,\n workflowRunId: data.workflowRunId,\n stageId: data.stageId,\n stageName: data.stageName,\n stageNumber: data.stageNumber,\n executionGroup: data.executionGroup,\n status: data.status ?? \"PENDING\",\n startedAt: data.startedAt ?? null,\n completedAt: null,\n duration: null,\n inputData: data.inputData ?? null,\n outputData: null,\n config: data.config ?? null,\n suspendedState: null,\n resumeData: null,\n nextPollAt: null,\n pollInterval: null,\n maxWaitUntil: null,\n metrics: null,\n embeddingInfo: null,\n errorMessage: null,\n };\n\n this.stages.set(id, record);\n // Also index by composite key for lookups\n this.stages.set(this.stageKey(data.workflowRunId, data.stageId), record);\n return { ...record };\n }\n\n async upsertStage(data: UpsertStageInput): Promise<WorkflowStageRecord> {\n const key = this.stageKey(data.workflowRunId, data.stageId);\n const existing = this.stages.get(key);\n\n if (existing) {\n const updated: WorkflowStageRecord = {\n ...existing,\n ...data.update,\n updatedAt: new Date(),\n version: existing.version + 1,\n };\n this.stages.set(existing.id, updated);\n this.stages.set(key, updated);\n return { ...updated };\n } else {\n return this.createStage(data.create);\n }\n }\n\n async updateStage(id: string, data: UpdateStageInput): Promise<void> {\n const stage = this.stages.get(id);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${id}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n id,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(id, updated);\n this.stages.set(this.stageKey(stage.workflowRunId, stage.stageId), updated);\n }\n\n async updateStageByRunAndStageId(\n workflowRunId: string,\n stageId: string,\n data: UpdateStageInput,\n ): Promise<void> {\n const key = this.stageKey(workflowRunId, stageId);\n const stage = this.stages.get(key);\n if (!stage) {\n throw new Error(`WorkflowStage not found: ${workflowRunId}/${stageId}`);\n }\n\n if (\n data.expectedVersion !== undefined &&\n stage.version !== data.expectedVersion\n ) {\n throw new StaleVersionError(\n \"WorkflowStage\",\n `${workflowRunId}/${stageId}`,\n data.expectedVersion,\n stage.version,\n );\n }\n\n const { expectedVersion: _, ...rest } = data;\n const updated: WorkflowStageRecord = {\n ...stage,\n ...rest,\n updatedAt: new Date(),\n version: stage.version + 1,\n };\n this.stages.set(stage.id, updated);\n this.stages.set(key, updated);\n }\n\n async getStage(\n runId: string,\n stageId: string,\n ): Promise<WorkflowStageRecord | null> {\n const key = this.stageKey(runId, stageId);\n const stage = this.stages.get(key);\n return stage ? { ...stage } : null;\n }\n\n async getStageById(id: string): Promise<WorkflowStageRecord | null> {\n const stage = this.stages.get(id);\n return stage ? { ...stage } : null;\n }\n\n async getStagesByRun(\n runId: string,\n options?: { status?: WorkflowStageStatus; orderBy?: \"asc\" | \"desc\" },\n ): Promise<WorkflowStageRecord[]> {\n // Use a Set to track seen IDs and avoid duplicates from composite keys\n const seenIds = new Set<string>();\n let stages = Array.from(this.stages.values()).filter((s) => {\n if (s.workflowRunId !== runId) return false;\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return true;\n });\n\n if (options?.status) {\n stages = stages.filter((s) => s.status === options.status);\n }\n\n // Sort by stageNumber\n stages.sort((a, b) => {\n const diff = a.stageNumber - b.stageNumber;\n return options?.orderBy === \"desc\" ? -diff : diff;\n });\n\n return stages.map((s) => ({ ...s }));\n }\n\n async getSuspendedStages(beforeDate: Date): Promise<WorkflowStageRecord[]> {\n const seenIds = new Set<string>();\n return Array.from(this.stages.values())\n .filter((s) => {\n if (seenIds.has(s.id)) return false;\n seenIds.add(s.id);\n return (\n s.status === \"SUSPENDED\" &&\n s.nextPollAt !== null &&\n s.nextPollAt <= beforeDate\n );\n })\n .map((s) => ({ ...s }));\n }\n\n async getFirstSuspendedStageReadyToResume(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"SUSPENDED\" });\n const now = new Date();\n const ready = stages.find((s) => s.nextPollAt && s.nextPollAt <= now);\n return ready ?? null;\n }\n\n async getFirstFailedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, { status: \"FAILED\" });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStage(\n runId: string,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n return stages[0] ?? null;\n }\n\n async getLastCompletedStageBefore(\n runId: string,\n executionGroup: number,\n ): Promise<WorkflowStageRecord | null> {\n const stages = await this.getStagesByRun(runId, {\n status: \"COMPLETED\",\n orderBy: \"desc\",\n });\n const before = stages.filter((s) => s.executionGroup < executionGroup);\n return before[0] ?? null;\n }\n\n async deleteStage(id: string): Promise<void> {\n const stage = this.stages.get(id);\n if (stage) {\n this.stages.delete(id);\n this.stages.delete(this.stageKey(stage.workflowRunId, stage.stageId));\n }\n }\n\n // ============================================================================\n // WorkflowLog Operations\n // ============================================================================\n\n async createLog(data: CreateLogInput): Promise<void> {\n const record: WorkflowLogRecord = {\n id: randomUUID(),\n createdAt: new Date(),\n workflowRunId: data.workflowRunId ?? null,\n workflowStageId: data.workflowStageId ?? null,\n level: data.level,\n message: data.message,\n metadata: data.metadata ?? null,\n };\n this.logs.set(record.id, record);\n }\n\n // ============================================================================\n // Outbox Operations\n // ============================================================================\n\n async appendOutboxEvents(events: CreateOutboxEventInput[]): Promise<void> {\n for (const event of events) {\n const currentSeq = this.outboxSequences.get(event.workflowRunId) ?? 0;\n const nextSeq = currentSeq + 1;\n this.outboxSequences.set(event.workflowRunId, nextSeq);\n\n const record: OutboxRecord = {\n id: randomUUID(),\n workflowRunId: event.workflowRunId,\n sequence: nextSeq,\n eventType: event.eventType,\n payload: event.payload,\n causationId: event.causationId,\n occurredAt: event.occurredAt,\n publishedAt: null,\n retryCount: 0,\n dlqAt: null,\n };\n this.outbox.push(record);\n }\n }\n\n async getUnpublishedOutboxEvents(limit?: number): Promise<OutboxRecord[]> {\n const effectiveLimit = limit ?? 100;\n return this.outbox\n .filter((r) => r.publishedAt === null && r.dlqAt === null)\n .sort((a, b) => {\n const runCmp = a.workflowRunId.localeCompare(b.workflowRunId);\n if (runCmp !== 0) return runCmp;\n return a.sequence - b.sequence;\n })\n .slice(0, effectiveLimit)\n .map((r) => ({ ...r }));\n }\n\n async markOutboxEventsPublished(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n for (const record of this.outbox) {\n if (idSet.has(record.id)) {\n record.publishedAt = new Date();\n }\n }\n }\n\n async incrementOutboxRetryCount(id: string): Promise<number> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.retryCount++;\n return record.retryCount;\n }\n\n async moveOutboxEventToDLQ(id: string): Promise<void> {\n const record = this.outbox.find((r) => r.id === id);\n if (!record) throw new Error(`Outbox event not found: ${id}`);\n record.dlqAt = new Date();\n }\n\n async replayDLQEvents(maxEvents: number): Promise<number> {\n const dlqEvents = this.outbox\n .filter((r) => r.dlqAt !== null)\n .slice(0, maxEvents);\n for (const record of dlqEvents) {\n record.dlqAt = null;\n record.retryCount = 0;\n }\n return dlqEvents.length;\n }\n\n // ============================================================================\n // Idempotency Operations\n // ============================================================================\n\n async acquireIdempotencyKey(\n key: string,\n commandType: string,\n ): Promise<\n | { status: \"acquired\" }\n | { status: \"replay\"; result: unknown }\n | { status: \"in_progress\" }\n > {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n const record = this.idempotencyKeys.get(compositeKey);\n if (record) {\n return { status: \"replay\", result: record.result };\n }\n if (this.idempotencyInProgress.has(compositeKey)) {\n return { status: \"in_progress\" };\n }\n this.idempotencyInProgress.add(compositeKey);\n return { status: \"acquired\" };\n }\n\n async completeIdempotencyKey(\n key: string,\n commandType: string,\n result: unknown,\n ): Promise<void> {\n const compositeKey = this.idempotencyCompositeKey(commandType, key);\n this.idempotencyInProgress.delete(compositeKey);\n this.idempotencyKeys.set(compositeKey, {\n key,\n commandType,\n result,\n createdAt: new Date(),\n });\n }\n\n async releaseIdempotencyKey(key: string, commandType: string): Promise<void> {\n this.idempotencyInProgress.delete(\n this.idempotencyCompositeKey(commandType, key),\n );\n }\n\n // ============================================================================\n // WorkflowArtifact Operations\n // ============================================================================\n\n async saveArtifact(data: SaveArtifactInput): Promise<void> {\n const now = new Date();\n const key = this.artifactKey(data.workflowRunId, data.key);\n const existing = this.artifacts.get(key);\n\n const record: WorkflowArtifactRecord = {\n id: existing?.id ?? randomUUID(),\n createdAt: existing?.createdAt ?? now,\n updatedAt: now,\n workflowRunId: data.workflowRunId,\n workflowStageId: data.workflowStageId ?? null,\n key: data.key,\n type: data.type,\n data: data.data,\n size: data.size,\n metadata: data.metadata ?? null,\n };\n this.artifacts.set(key, record);\n }\n\n async loadArtifact(runId: string, key: string): Promise<unknown> {\n const artifact = this.artifacts.get(this.artifactKey(runId, key));\n if (!artifact) {\n throw new Error(`Artifact not found: ${runId}/${key}`);\n }\n return artifact.data;\n }\n\n async hasArtifact(runId: string, key: string): Promise<boolean> {\n return this.artifacts.has(this.artifactKey(runId, key));\n }\n\n async deleteArtifact(runId: string, key: string): Promise<void> {\n this.artifacts.delete(this.artifactKey(runId, key));\n }\n\n async listArtifacts(runId: string): Promise<WorkflowArtifactRecord[]> {\n return Array.from(this.artifacts.values())\n .filter((a) => a.workflowRunId === runId)\n .map((a) => ({ ...a }));\n }\n\n async getStageIdForArtifact(\n runId: string,\n stageId: string,\n ): Promise<string | null> {\n const stage = await this.getStage(runId, stageId);\n return stage?.id ?? null;\n }\n\n // ============================================================================\n // Stage Output Convenience Method\n // ============================================================================\n\n async saveStageOutput(\n runId: string,\n workflowType: string,\n stageId: string,\n output: unknown,\n ): Promise<string> {\n const key = `workflow-v2/${workflowType}/${runId}/${stageId}/output.json`;\n const stageDbId = await this.getStageIdForArtifact(runId, stageId);\n\n await this.saveArtifact({\n workflowRunId: runId,\n workflowStageId: stageDbId ?? undefined,\n key,\n type: \"STAGE_OUTPUT\",\n data: output,\n size: JSON.stringify(output).length,\n });\n\n return key;\n }\n\n // ============================================================================\n // Test Helpers\n // ============================================================================\n\n /**\n * Clear all data - useful between tests\n */\n clear(): void {\n this.runs.clear();\n this.stages.clear();\n this.logs.clear();\n this.artifacts.clear();\n this.outbox = [];\n this.idempotencyKeys.clear();\n this.idempotencyInProgress.clear();\n this.outboxSequences.clear();\n }\n\n /**\n * Get all runs for inspection\n */\n getAllRuns(): WorkflowRunRecord[] {\n return Array.from(this.runs.values()).map((r) => ({ ...r }));\n }\n\n /**\n * Get all stages for inspection\n */\n getAllStages(): WorkflowStageRecord[] {\n // Filter out composite key duplicates\n return Array.from(this.stages.values())\n .filter((s) => this.stages.get(s.id) === s)\n .map((s) => ({ ...s }));\n }\n\n /**\n * Get all logs for inspection\n */\n getAllLogs(): WorkflowLogRecord[] {\n return Array.from(this.logs.values()).map((l) => ({ ...l }));\n }\n\n /**\n * Get all artifacts for inspection\n */\n getAllArtifacts(): WorkflowArtifactRecord[] {\n return Array.from(this.artifacts.values()).map((a) => ({ ...a }));\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bratsos/workflow-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Type-safe, distributed workflow engine for AI-orchestrated processes with suspend/resume, parallel execution, and cost tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -4,7 +4,7 @@ description: Guide for @bratsos/workflow-engine - a type-safe workflow engine wi
|
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: bratsos
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.3.0"
|
|
8
8
|
repository: https://github.com/bratsos/workflow-engine
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -109,6 +109,10 @@ await kernel.dispatch({
|
|
|
109
109
|
| `createServerlessHost` | Function | `@bratsos/workflow-engine-host-serverless` | Create serverless host |
|
|
110
110
|
| `createAIHelper` | Function | `@bratsos/workflow-engine` | AI operations (text, object, embed, batch) |
|
|
111
111
|
| `registerEmbeddingProvider` | Function | `@bratsos/workflow-engine` | Register custom embedding providers (Voyage, Cohere, etc.) |
|
|
112
|
+
| `createStageIds` | Function | `@bratsos/workflow-engine` | Create stage ID constants from a workflow |
|
|
113
|
+
| `defineStageIds` | Function | `@bratsos/workflow-engine` | Define stage ID constants from a tuple |
|
|
114
|
+
| `isValidStageId` | Function | `@bratsos/workflow-engine` | Runtime stage ID validation |
|
|
115
|
+
| `assertValidStageId` | Function | `@bratsos/workflow-engine` | Assert stage ID validity (throws) |
|
|
112
116
|
| `definePlugin` | Function | `@bratsos/workflow-engine/kernel` | Define kernel plugins |
|
|
113
117
|
| `createPluginRunner` | Function | `@bratsos/workflow-engine/kernel` | Create plugin event processor |
|
|
114
118
|
|
|
@@ -121,10 +125,10 @@ All operations go through `kernel.dispatch(command)`:
|
|
|
121
125
|
| `run.create` | Create a new workflow run |
|
|
122
126
|
| `run.claimPending` | Claim pending runs, enqueue first-stage jobs |
|
|
123
127
|
| `run.transition` | Advance to next stage group or complete |
|
|
124
|
-
| `run.cancel` | Cancel a running workflow |
|
|
125
|
-
| `run.rerunFrom` | Rerun from a specific stage |
|
|
128
|
+
| `run.cancel` | Cancel a running workflow (authoritative: cascades to stages + jobs) |
|
|
129
|
+
| `run.rerunFrom` | Rerun from a specific stage (cleans up blob artifacts by prefix) |
|
|
126
130
|
| `job.execute` | Execute a single stage (uses multi-phase transactions; see 08-common-patterns.md) |
|
|
127
|
-
| `stage.pollSuspended` | Poll suspended stages for readiness (
|
|
131
|
+
| `stage.pollSuspended` | Poll suspended stages for readiness (skips cancelled runs; per-stage transactions) |
|
|
128
132
|
| `lease.reapStale` | Release stale job leases |
|
|
129
133
|
| `run.reapStuck` | Detect and fail RUNNING runs with no recent activity |
|
|
130
134
|
| `outbox.flush` | Publish pending outbox events |
|
|
@@ -179,7 +183,12 @@ const batchStage = defineAsyncBatchStage({
|
|
|
179
183
|
const batchId = await submitBatchJob(ctx.input);
|
|
180
184
|
return {
|
|
181
185
|
suspended: true,
|
|
182
|
-
state: {
|
|
186
|
+
state: {
|
|
187
|
+
batchId,
|
|
188
|
+
submittedAt: new Date().toISOString(),
|
|
189
|
+
pollInterval: 60000,
|
|
190
|
+
maxWaitTime: 3600000,
|
|
191
|
+
},
|
|
183
192
|
pollConfig: { pollInterval: 60000, maxWaitTime: 3600000, nextPollAt: new Date(Date.now() + 60000) },
|
|
184
193
|
};
|
|
185
194
|
},
|
|
@@ -195,23 +204,31 @@ const batchStage = defineAsyncBatchStage({
|
|
|
195
204
|
|
|
196
205
|
## WorkflowBuilder
|
|
197
206
|
|
|
207
|
+
Workflows are linear pipelines of **execution groups**. `.pipe()` creates single-stage groups; `.parallel()` creates multi-stage groups. Parallel group outputs are keyed by stage ID in the workflow context.
|
|
208
|
+
|
|
198
209
|
```typescript
|
|
199
210
|
const workflow = new WorkflowBuilder(
|
|
200
211
|
"workflow-id", "Workflow Name", "Description",
|
|
201
212
|
InputSchema, OutputSchema
|
|
202
213
|
)
|
|
203
|
-
.pipe(stage1)
|
|
204
|
-
.pipe(stage2)
|
|
205
|
-
.parallel([stage3a, stage3b])
|
|
206
|
-
.pipe(stage4)
|
|
214
|
+
.pipe(stage1) // Group 0
|
|
215
|
+
.pipe(stage2) // Group 1
|
|
216
|
+
.parallel([stage3a, stage3b]) // Group 2 (concurrent, output: { "stage3a-id": ..., "stage3b-id": ... })
|
|
217
|
+
.pipe(stage4) // Group 3
|
|
207
218
|
.build();
|
|
208
219
|
|
|
220
|
+
// In stage4, access parallel outputs by stage ID:
|
|
221
|
+
ctx.require("stage3a-id") // output of stage3a
|
|
222
|
+
ctx.require("stage3b-id") // output of stage3b
|
|
223
|
+
|
|
209
224
|
workflow.getStageIds();
|
|
210
225
|
workflow.getExecutionPlan();
|
|
211
226
|
workflow.getDefaultConfig();
|
|
212
227
|
workflow.validateConfig(config);
|
|
213
228
|
```
|
|
214
229
|
|
|
230
|
+
When a workflow completes, the final execution group's output is persisted in `WorkflowRun.output` and included in the `workflow:completed` event.
|
|
231
|
+
|
|
215
232
|
## Kernel Setup
|
|
216
233
|
|
|
217
234
|
```typescript
|
|
@@ -438,5 +455,7 @@ await kernel.dispatch({ type: "run.transition", workflowRunId: job.workflowRunId
|
|
|
438
455
|
4. **Context Access**: Use `ctx.require()` and `ctx.optional()` for type-safe stage output access
|
|
439
456
|
5. **Transactional Outbox**: Events written to outbox, published via `outbox.flush` command. `job.execute` and `stage.pollSuspended` use multi-phase transactions to avoid holding connections during external I/O
|
|
440
457
|
6. **Idempotency**: `run.create` and `job.execute` replay cached results by key; concurrent same-key dispatch throws `IdempotencyInProgressError`
|
|
441
|
-
7. **
|
|
442
|
-
8. **
|
|
458
|
+
7. **Authoritative Cancellation**: `run.cancel` cascades to stages + jobs. Ghost jobs (running against non-RUNNING runs) are detected via `ghost: true` flag and not retried
|
|
459
|
+
8. **Self-Healing**: Stage creation is idempotent (upsert), orchestration steps are isolated, stuck runs are automatically reaped
|
|
460
|
+
9. **Cost Tracking**: All AI calls automatically track tokens and costs
|
|
461
|
+
10. **BlobStore-Only Artifacts**: All artifact storage goes through the BlobStore port. `run.rerunFrom` cleans up artifacts by key prefix
|
|
@@ -55,6 +55,8 @@ Parallel stages:
|
|
|
55
55
|
- Run in the same execution group
|
|
56
56
|
- Receive the same input (output from previous group)
|
|
57
57
|
- Must not depend on each other
|
|
58
|
+
- Their outputs are merged into the workflow context keyed by stage ID (e.g., `{ "classify": classifyOutput, "summarize": summarizeOutput }`)
|
|
59
|
+
- Subsequent stages access each parallel stage's output via `ctx.require("classify")`, `ctx.require("summarize")`, etc.
|
|
58
60
|
|
|
59
61
|
### build()
|
|
60
62
|
|
|
@@ -58,7 +58,7 @@ const kernel = createKernel({
|
|
|
58
58
|
|------|-----------|---------|
|
|
59
59
|
| `persistence` | `Persistence` | CRUD for runs, stages, logs, outbox events, idempotency keys |
|
|
60
60
|
| `blobStore` | `BlobStore` | `put(key, data)`, `get(key)`, `has(key)`, `delete(key)`, `list(prefix)` |
|
|
61
|
-
| `jobTransport` | `JobTransport` | `enqueue`, `enqueueParallel`, `dequeue`, `complete`, `suspend`, `fail` |
|
|
61
|
+
| `jobTransport` | `JobTransport` | `enqueue`, `enqueueParallel`, `dequeue`, `complete`, `suspend`, `fail`, `cancelByRun` |
|
|
62
62
|
| `eventSink` | `EventSink` | `emit(event)` - async event publishing |
|
|
63
63
|
| `scheduler` | `Scheduler` | `schedule(type, payload, runAt)`, `cancel(type, correlationId)` |
|
|
64
64
|
| `clock` | `Clock` | `now()` - returns `Date` |
|
|
@@ -96,6 +96,7 @@ const { deletedStages } = await kernel.dispatch({
|
|
|
96
96
|
|
|
97
97
|
// Stages from "summarize" onward are deleted and re-queued
|
|
98
98
|
// Earlier stages (e.g., "extract") keep their outputs
|
|
99
|
+
// Blob artifacts for deleted stages are cleaned up by key prefix
|
|
99
100
|
```
|
|
100
101
|
|
|
101
102
|
## Plugin System
|
|
@@ -213,7 +214,7 @@ If claiming a specific run fails (e.g., workflow not found, database error), tha
|
|
|
213
214
|
|
|
214
215
|
### Ghost Job Guard
|
|
215
216
|
|
|
216
|
-
`job.execute` verifies the run is in `RUNNING` status before executing. Jobs for `
|
|
217
|
+
`job.execute` verifies the run is in `RUNNING` status both before and after executing the stage. Jobs for non-`RUNNING` runs are discarded with `outcome: "failed"` and a `ghost: true` flag in the result. Hosts check this flag to disable retries (`canRetry = false`). This prevents ghost jobs from rolled-back transactions or concurrent cancellations from resurrecting invalid state.
|
|
217
218
|
|
|
218
219
|
### Orchestration Tick Isolation
|
|
219
220
|
|
|
@@ -62,9 +62,10 @@ await kernel.dispatch({ type: "run.transition", workflowRunId: runId });
|
|
|
62
62
|
|
|
63
63
|
**What it was:** If the kernel transaction rolled back after `jobTransport.enqueueParallel` committed (separate transaction), ghost jobs would exist in the queue pointing to runs/stages that were rolled back.
|
|
64
64
|
|
|
65
|
-
**How it's fixed (
|
|
66
|
-
1. **
|
|
67
|
-
2. **
|
|
65
|
+
**How it's fixed (three layers):**
|
|
66
|
+
1. **Authoritative cancellation:** `run.cancel` cancels all queued/suspended jobs via `jobTransport.cancelByRun()`, preventing most ghost jobs before dequeue.
|
|
67
|
+
2. **Kernel guard:** `job.execute` checks `workflowRun.status === "RUNNING"` both before AND after stage execution. Ghost jobs are discarded with `outcome: "failed"` and a typed `ghost: true` flag in the result.
|
|
68
|
+
3. **Host no-retry:** Both Node and Serverless hosts detect ghost jobs via the `ghost: true` flag (not string matching) and set `canRetry = false`, preventing infinite retry loops.
|
|
68
69
|
|
|
69
70
|
## One Bad Run Blocks Everything
|
|
70
71
|
|