@sonamu-kit/tasks 0.1.0 → 0.1.2

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.
Files changed (51) hide show
  1. package/dist/client.d.ts +0 -1
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +0 -1
  4. package/dist/client.js.map +1 -1
  5. package/dist/client.test.js +2 -1
  6. package/dist/client.test.js.map +1 -1
  7. package/dist/core/duration.d.ts +1 -1
  8. package/dist/core/duration.js +1 -1
  9. package/dist/core/duration.js.map +1 -1
  10. package/dist/core/workflow.d.ts +2 -1
  11. package/dist/core/workflow.d.ts.map +1 -1
  12. package/dist/core/workflow.js +2 -1
  13. package/dist/core/workflow.js.map +1 -1
  14. package/dist/database/backend.d.ts +7 -8
  15. package/dist/database/backend.d.ts.map +1 -1
  16. package/dist/database/backend.js +134 -39
  17. package/dist/database/backend.js.map +1 -1
  18. package/dist/database/backend.test.js +3 -1
  19. package/dist/database/backend.test.js.map +1 -1
  20. package/dist/database/base.d.ts +2 -2
  21. package/dist/database/base.d.ts.map +1 -1
  22. package/dist/database/base.js +17 -5
  23. package/dist/database/base.js.map +1 -1
  24. package/dist/database/pubsub.d.ts.map +1 -1
  25. package/dist/database/pubsub.js +9 -3
  26. package/dist/database/pubsub.js.map +1 -1
  27. package/dist/execution.test.js +4 -2
  28. package/dist/execution.test.js.map +1 -1
  29. package/dist/practices/01-remote-workflow.js +2 -1
  30. package/dist/practices/01-remote-workflow.js.map +1 -1
  31. package/dist/testing/connection.d.ts +1 -1
  32. package/dist/testing/connection.d.ts.map +1 -1
  33. package/dist/testing/connection.js +5 -4
  34. package/dist/testing/connection.js.map +1 -1
  35. package/dist/worker.test.js +2 -1
  36. package/dist/worker.test.js.map +1 -1
  37. package/package.json +7 -5
  38. package/scripts/migrate.ts +1 -4
  39. package/src/client.test.ts +2 -1
  40. package/src/client.ts +0 -1
  41. package/src/core/duration.ts +1 -1
  42. package/src/core/workflow.ts +2 -1
  43. package/src/database/backend.test.ts +3 -1
  44. package/src/database/backend.ts +140 -45
  45. package/src/database/base.ts +12 -7
  46. package/src/database/pubsub.ts +9 -3
  47. package/src/execution.test.ts +4 -2
  48. package/src/practices/01-remote-workflow.ts +2 -1
  49. package/src/testing/connection.ts +5 -3
  50. package/src/worker.test.ts +2 -1
  51. package/templates/openworkflow.config.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/worker.test.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { afterEach, beforeEach, describe, expect, test } from \"vitest\";\nimport { declareWorkflow, OpenWorkflow } from \"./client\";\nimport { BackendPostgres } from \"./database/backend\";\nimport { KNEX_GLOBAL_CONFIG } from \"./testing/connection\";\n\ndescribe(\"Worker\", () => {\n let backend: BackendPostgres;\n\n beforeEach(async () => {\n backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n });\n\n afterEach(async () => {\n await backend.stop();\n });\n\n test(\"passes workflow input to handlers (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"context\" }, ({ input }) => input);\n const worker = client.newWorker();\n\n const payload = { value: 10 };\n const handle = await workflow.run(payload);\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual(payload);\n });\n\n test(\"processes workflow runs to completion (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"process\" },\n ({ input }: { input: { value: number } }) => input.value * 2,\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run({ value: 21 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(42);\n });\n\n test(\"step.run reuses cached results (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"cached-step\" }, async ({ step }) => {\n const first = await step.run({ name: \"once\" }, () => {\n executionCount++;\n return \"value\";\n });\n const second = await step.run({ name: \"once\" }, () => {\n executionCount++;\n return \"should-not-run\";\n });\n return { first, second };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ first: \"value\", second: \"value\" });\n expect(executionCount).toBe(1);\n });\n\n test(\"marks workflow for retry when definition is missing\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"missing\",\n version: null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n const worker = client.newWorker();\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toBeDefined();\n expect(updated?.availableAt).not.toBeNull();\n });\n\n test(\"retries failed workflows automatically (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let attemptCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"retry-test\" }, () => {\n attemptCount++;\n if (attemptCount < 2) {\n throw new Error(`Attempt ${String(attemptCount)} failed`);\n }\n return { success: true, attempts: attemptCount };\n });\n\n const worker = client.newWorker();\n\n // run the workflow\n const handle = await workflow.run();\n\n // first attempt - will fail and reschedule\n await worker.tick();\n await sleep(100); // wait for worker to finish\n expect(attemptCount).toBe(1);\n\n await sleep(1100); // wait for backoff delay\n\n // second attempt - will succeed\n await worker.tick();\n await sleep(100); // wait for worker to finish\n expect(attemptCount).toBe(2);\n\n const result = await handle.result();\n expect(result).toEqual({ success: true, attempts: 2 });\n });\n\n test(\"tick is a no-op when no work is available\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"noop\" }, () => null);\n const worker = client.newWorker();\n await worker.tick(); // no runs queued\n });\n\n test(\"handles step functions that return undefined (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"undefined-steps\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => {\n return; // explicit undefined\n });\n await step.run({ name: \"step-2\" }, () => {\n // implicit undefined\n });\n return { success: true };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ success: true });\n });\n\n test(\"executes steps synchronously within workflow (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionOrder: string[] = [];\n const workflow = client.defineWorkflow({ name: \"sync-steps\" }, async ({ step }) => {\n executionOrder.push(\"start\");\n await step.run({ name: \"step1\" }, () => {\n executionOrder.push(\"step1\");\n return 1;\n });\n executionOrder.push(\"between\");\n await step.run({ name: \"step2\" }, () => {\n executionOrder.push(\"step2\");\n return 2;\n });\n executionOrder.push(\"end\");\n return executionOrder;\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual([\"start\", \"step1\", \"between\", \"step2\", \"end\"]);\n });\n\n test(\"executes parallel steps with Promise.all (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionTimes: Record<string, number> = {};\n const workflow = client.defineWorkflow({ name: \"parallel\" }, async ({ step }) => {\n const start = Date.now();\n const [a, b, c] = await Promise.all([\n step.run({ name: \"step-a\" }, () => {\n executionTimes[\"step-a\"] = Date.now() - start;\n return \"a\";\n }),\n step.run({ name: \"step-b\" }, () => {\n executionTimes[\"step-b\"] = Date.now() - start;\n return \"b\";\n }),\n step.run({ name: \"step-c\" }, () => {\n executionTimes[\"step-c\"] = Date.now() - start;\n return \"c\";\n }),\n ]);\n return { a, b, c };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ a: \"a\", b: \"b\", c: \"c\" });\n\n // steps should execute at roughly the same time (within 100ms)\n const times = Object.values(executionTimes);\n const maxTime = Math.max(...times);\n const minTime = Math.min(...times);\n expect(maxTime - minTime).toBeLessThan(100);\n });\n\n test(\"respects worker concurrency limit\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"concurrency-test\" }, () => {\n return \"done\";\n });\n\n const worker = client.newWorker({ concurrency: 2 });\n\n // create 5 workflow runs, though only 2 (concurrency limit) should be\n // completed per tick\n const handles = await Promise.all([\n workflow.run(),\n workflow.run(),\n workflow.run(),\n workflow.run(),\n workflow.run(),\n ]);\n\n await worker.tick();\n await sleep(100);\n\n let completed = 0;\n for (const handle of handles) {\n const run = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n if (run?.status === \"completed\") completed++;\n }\n\n expect(completed).toBe(2);\n });\n\n test(\"worker starts, processes work, and stops gracefully (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"lifecycle\" }, () => {\n return \"complete\";\n });\n\n const worker = client.newWorker();\n\n await worker.start();\n const handle = await workflow.run();\n await sleep(200);\n await worker.stop();\n\n const result = await handle.result();\n expect(result).toBe(\"complete\");\n });\n\n test(\"recovers from crashes during parallel step execution (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let attemptCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"crash-recovery\" }, async ({ step }) => {\n attemptCount++;\n\n const [a, b] = await Promise.all([\n step.run({ name: \"step-a\" }, () => {\n if (attemptCount > 1) return \"x\"; // should not happen since \"a\" will be cached\n return \"a\";\n }),\n step.run({ name: \"step-b\" }, () => {\n if (attemptCount === 1) throw new Error(\"Simulated crash\");\n return \"b\";\n }),\n ]);\n\n return { a, b, attempts: attemptCount };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n\n // first attempt will fail\n await worker.tick();\n await sleep(100);\n expect(attemptCount).toBe(1);\n\n // wait for backoff\n await sleep(1100);\n\n // second attempt should succeed\n await worker.tick();\n await sleep(100);\n\n const result = await handle.result();\n expect(result).toEqual({ a: \"a\", b: \"b\", attempts: 2 });\n expect(attemptCount).toBe(2);\n });\n\n test(\"reclaims workflow run when heartbeat stops (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"heartbeat-test\" }, () => \"done\");\n\n const handle = await workflow.run();\n const workerId = randomUUID();\n\n const claimed = await backend.claimWorkflowRun({\n workerId,\n leaseDurationMs: 50,\n });\n expect(claimed).not.toBeNull();\n\n // let lease expire before starting worker\n await sleep(100);\n\n // worker should be able to reclaim\n const worker = client.newWorker();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n });\n\n test(\"tick() returns count of claimed workflows\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"count-test\" }, () => \"result\");\n\n // enqueue 3 workflows\n await workflow.run();\n await workflow.run();\n await workflow.run();\n\n const worker = client.newWorker({ concurrency: 5 });\n\n // first tick should claim 3 workflows (all available)\n const claimed = await worker.tick();\n expect(claimed).toBe(3);\n\n // second tick should claim 0 (all already claimed)\n const claimedAgain = await worker.tick();\n expect(claimedAgain).toBe(0);\n\n await worker.stop();\n });\n\n test(\"tick() respects concurrency limit\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"concurrency-test\" }, async () => {\n await sleep(100);\n return \"done\";\n });\n\n // enqueue 10 workflows\n for (let i = 0; i < 10; i++) {\n await workflow.run();\n }\n\n const worker = client.newWorker({ concurrency: 3 });\n\n // first tick should claim exactly 3 (concurrency limit)\n const claimed = await worker.tick();\n expect(claimed).toBe(3);\n\n // second tick should claim 0 (all slots occupied)\n const claimedAgain = await worker.tick();\n expect(claimedAgain).toBe(0);\n\n await worker.stop();\n });\n\n test(\"worker only sleeps between claims when no work is available (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"adaptive-test\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => \"done\");\n return \"complete\";\n });\n\n // enqueue many workflows\n const handles = [];\n for (let i = 0; i < 20; i++) {\n handles.push(await workflow.run());\n }\n\n const worker = client.newWorker({ concurrency: 5 });\n\n const startTime = Date.now();\n await worker.start();\n\n // wait for all workflows to complete\n await Promise.all(handles.map((h) => h.result()));\n await worker.stop();\n\n const duration = Date.now() - startTime;\n\n // with this conditional sleep, all workflows should complete quickly\n // without it (with 100ms sleep between ticks), it would take much longer\n expect(duration).toBeLessThan(3000); // should complete in under 3 seconds\n });\n\n test(\"only failed steps re-execute on retry (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionCounts = {\n stepA: 0,\n stepB: 0,\n stepC: 0,\n };\n\n const workflow = client.defineWorkflow({ name: \"mixed-retry\" }, async ({ step }) => {\n const a = await step.run({ name: \"step-a\" }, () => {\n executionCounts.stepA++;\n return \"a-result\";\n });\n\n const b = await step.run({ name: \"step-b\" }, () => {\n executionCounts.stepB++;\n if (executionCounts.stepB === 1) {\n throw new Error(\"Step B fails on first attempt\");\n }\n return \"b-result\";\n });\n\n const c = await step.run({ name: \"step-c\" }, () => {\n executionCounts.stepC++;\n return \"c-result\";\n });\n\n return { a, b, c };\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first workflow attempt\n // - step-a succeeds\n // - step-b fails\n // - step-c never runs (workflow fails at step-b)\n await worker.tick();\n await sleep(100);\n expect(executionCounts.stepA).toBe(1);\n expect(executionCounts.stepB).toBe(1);\n expect(executionCounts.stepC).toBe(0);\n\n // wait for backoff\n await sleep(1100);\n\n // second workflow attempt\n // - step-a should be cached (not re-executed)\n // - step-b should be re-executed (failed previously)\n // - step-c should execute for first time\n await worker.tick();\n await sleep(100);\n expect(executionCounts.stepA).toBe(1); // still 1, was cached\n expect(executionCounts.stepB).toBe(2); // incremented, was retried\n expect(executionCounts.stepC).toBe(1); // incremented, first execution\n\n const result = await handle.result();\n expect(result).toEqual({\n a: \"a-result\",\n b: \"b-result\",\n c: \"c-result\",\n });\n });\n\n test(\"step.sleep postpones workflow execution (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let stepCount = 0;\n const workflow = client.defineWorkflow({ name: \"sleep-test\" }, async ({ step }) => {\n const before = await step.run({ name: \"before-sleep\" }, () => {\n stepCount++;\n return \"before\";\n });\n\n await step.sleep(\"pause\", \"100ms\");\n\n const after = await step.run({ name: \"after-sleep\" }, () => {\n stepCount++;\n return \"after\";\n });\n\n return { before, after };\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution - runs before-sleep, then sleeps\n await worker.tick();\n await sleep(50); // wait for processing\n expect(stepCount).toBe(1);\n\n // verify workflow was postponed with sleeping status\n const slept = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(slept?.status).toBe(\"sleeping\");\n expect(slept?.workerId).toBeNull(); // released during sleep\n expect(slept?.availableAt).not.toBeNull();\n if (!slept?.availableAt) throw new Error(\"availableAt should be set\");\n const delayMs = slept.availableAt.getTime() - Date.now();\n expect(delayMs).toBeGreaterThan(0);\n expect(delayMs).toBeLessThan(150); // should be ~100ms\n\n // verify sleep step is in \"running\" state during sleep\n const attempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const sleepStep = attempts.data.find((a) => a.stepName === \"pause\");\n expect(sleepStep?.status).toBe(\"running\");\n\n // wait for sleep duration\n await sleep(150);\n\n // second execution (after sleep)\n await worker.tick();\n await sleep(50); // wait for processing\n expect(stepCount).toBe(2);\n\n // verify sleep step is now \"completed\"\n const refreshedAttempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const completedSleepStep = refreshedAttempts.data.find((a) => a.stepName === \"pause\");\n expect(completedSleepStep?.status).toBe(\"completed\");\n\n const result = await handle.result();\n expect(result).toEqual({ before: \"before\", after: \"after\" });\n });\n\n test(\"step.sleep is cached on replay\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let step1Count = 0;\n let step2Count = 0;\n const workflow = client.defineWorkflow({ name: \"sleep-cache-test\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => {\n step1Count++;\n return \"one\";\n });\n\n // this should only postpone once\n await step.sleep(\"wait\", \"50ms\");\n\n await step.run({ name: \"step-2\" }, () => {\n step2Count++;\n return \"two\";\n });\n\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first attempt: execute step-1, then sleep (step-2 not executed)\n await worker.tick();\n await sleep(50);\n expect(step1Count).toBe(1);\n expect(step2Count).toBe(0);\n\n await sleep(100); // wait for sleep to complete\n\n // second attempt: step-1 is cached (not re-executed), sleep is cached, step-2 executes\n await worker.tick();\n await sleep(50);\n expect(step1Count).toBe(1); // still 1, was cached\n expect(step2Count).toBe(1); // now 1, executed after sleep\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n });\n\n test(\"step.sleep throws error for invalid duration format\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"invalid-duration\" }, async ({ step }) => {\n // @ts-expect-error - testing invalid duration\n await step.sleep(\"bad\", \"invalid\");\n return \"should-not-reach\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n await worker.tick();\n await sleep(100);\n\n const failed = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n\n expect(failed?.status).toBe(\"pending\"); // should be retrying\n expect(failed?.error).toBeDefined();\n expect(failed?.error?.message).toContain(\"Invalid duration format\");\n });\n\n test(\"step.sleep handles multiple sequential sleeps (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"sequential-sleeps\" }, async ({ step }) => {\n executionCount++;\n\n await step.run({ name: \"step-1\" }, () => \"one\");\n await step.sleep(\"sleep-1\", \"50ms\");\n await step.run({ name: \"step-2\" }, () => \"two\");\n await step.sleep(\"sleep-2\", \"50ms\");\n await step.run({ name: \"step-3\" }, () => \"three\");\n\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution: step-1, then sleep-1\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(1);\n\n // verify first sleep is running\n const attempts1 = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(attempts1.data.find((a) => a.stepName === \"sleep-1\")?.status).toBe(\"running\");\n\n // wait for first sleep\n await sleep(100);\n\n // second execution: sleep-1 completed, step-2, then sleep-2\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(2);\n\n // verify second sleep is running\n const attempts2 = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(attempts2.data.find((a) => a.stepName === \"sleep-1\")?.status).toBe(\"completed\");\n expect(attempts2.data.find((a) => a.stepName === \"sleep-2\")?.status).toBe(\"running\");\n\n // wait for second sleep\n await sleep(100);\n\n // third execution: sleep-2 completed, step-3, complete\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(3);\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n\n // verify all steps completed\n const finalAttempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(finalAttempts.data.length).toBe(5); // 3 regular steps + 2 sleeps\n expect(finalAttempts.data.every((a) => a.status === \"completed\")).toBe(true);\n });\n\n test(\"sleeping workflows can be claimed after availableAt\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"sleeping-claim-test\" }, async ({ step }) => {\n await step.run({ name: \"before\" }, () => \"before\");\n await step.sleep(\"wait\", \"100ms\");\n await step.run({ name: \"after\" }, () => \"after\");\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution - sleep\n await worker.tick();\n await sleep(50);\n\n // verify workflow is in sleeping state\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n expect(sleeping?.workerId).toBeNull();\n\n // wait for sleep duration\n await sleep(100);\n\n // verify workflow can be claimed again\n const claimed = await backend.claimWorkflowRun({\n workerId: \"test-worker\",\n leaseDurationMs: 30_000,\n });\n expect(claimed?.id).toBe(handle.workflowRun.id);\n expect(claimed?.status).toBe(\"running\");\n expect(claimed?.workerId).toBe(\"test-worker\");\n });\n\n test(\"sleep is not skipped when worker crashes after creating sleep step but before marking workflow as sleeping (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n let beforeSleepCount = 0;\n let afterSleepCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"crash-during-sleep\" }, async ({ step }) => {\n executionCount++;\n\n await step.run({ name: \"before-sleep\" }, () => {\n beforeSleepCount++;\n return \"before\";\n });\n\n // this sleep should NOT be skipped even if crash happens\n await step.sleep(\"critical-pause\", \"200ms\");\n\n await step.run({ name: \"after-sleep\" }, () => {\n afterSleepCount++;\n return \"after\";\n });\n\n return { executionCount, beforeSleepCount, afterSleepCount };\n });\n\n const handle = await workflow.run();\n\n // first worker processes the workflow until sleep\n const worker1 = client.newWorker();\n await worker1.tick();\n await sleep(100);\n\n const workflowAfterFirst = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n\n expect(workflowAfterFirst?.status).toBe(\"sleeping\");\n\n const attemptsAfterFirst = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const sleepStep = attemptsAfterFirst.data.find((a) => a.stepName === \"critical-pause\");\n expect(sleepStep).toBeDefined();\n expect(sleepStep?.kind).toBe(\"sleep\");\n expect(sleepStep?.status).toBe(\"running\");\n\n await sleep(50); // only 50ms of the 200ms sleep\n\n // if there's a running sleep step, the workflow should be properly\n // transitioned to sleeping\n const worker2 = client.newWorker();\n await worker2.tick();\n\n // after-sleep step should NOT have executed yet\n expect(afterSleepCount).toBe(0);\n\n // wait for the full sleep duration to elapse then check to make sure\n // workflow is claimable and resume\n await sleep(200);\n await worker2.tick();\n await sleep(100);\n expect(afterSleepCount).toBe(1);\n const result = await handle.result();\n expect(result.afterSleepCount).toBe(1);\n });\n\n test(\"version enables conditional code paths (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"conditional-workflow\", version: \"v2\" },\n async ({ version, step }) => {\n return version === \"v1\"\n ? await step.run({ name: \"old-step\" }, () => \"old-logic\")\n : await step.run({ name: \"new-step\" }, () => \"new-logic\");\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"new-logic\");\n });\n\n test(\"workflow version is null when not specified\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"unversioned-workflow\" },\n async ({ version, step }) => {\n const result = await step.run({ name: \"check-version\" }, () => {\n return { version };\n });\n return result;\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result.version).toBeNull();\n });\n\n test(\"cancels a pending workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-pending\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => \"result\");\n return { completed: true };\n });\n\n const handle = await workflow.run();\n\n // cancel before worker processes it\n await handle.cancel();\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"canceled\");\n expect(workflowRun?.finishedAt).not.toBeNull();\n expect(workflowRun?.availableAt).toBeNull();\n expect(workflowRun?.workerId).toBeNull();\n });\n\n test(\"cancels a sleeping workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-sleeping\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"1h\");\n return { completed: true };\n });\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n // cancel while sleeping\n await handle.cancel();\n\n const canceled = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(canceled?.status).toBe(\"canceled\");\n expect(canceled?.finishedAt).not.toBeNull();\n expect(canceled?.availableAt).toBeNull();\n expect(canceled?.workerId).toBeNull();\n });\n\n test(\"cannot cancel a completed workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-completed\" }, () => ({\n completed: true,\n }));\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result.completed).toBe(true);\n\n // try to cancel after success\n await expect(handle.cancel()).rejects.toThrow(\n /Cannot cancel workflow run .* with status completed/,\n );\n });\n\n test(\"cannot cancel a failed workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-failed\" }, () => {\n throw new Error(\"intentional failure\");\n });\n const worker = client.newWorker();\n\n const handle = await workflow.run({ value: 1 }, { deadlineAt: new Date() });\n await worker.tick();\n\n // wait for it to fail due to deadline\n await sleep(100);\n\n const failed = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(failed?.status).toBe(\"failed\");\n\n // try to cancel after failure\n await expect(handle.cancel()).rejects.toThrow(\n /Cannot cancel workflow run .* with status failed/,\n );\n });\n\n test(\"cannot cancel non-existent workflow\", async () => {\n await expect(\n backend.cancelWorkflowRun({\n workflowRunId: \"non-existent-id\",\n }),\n ).rejects.toThrow(/Workflow run non-existent-id does not exist/);\n });\n\n test(\"worker handles when canceled workflow during execution\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let stepExecuted = false;\n const workflow = client.defineWorkflow(\n { name: \"cancel-during-execution\" },\n async ({ step }) => {\n await step.run({ name: \"step-1\" }, async () => {\n stepExecuted = true;\n // simulate some work\n await sleep(50);\n return \"result\";\n });\n return { completed: true };\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n\n // start processing in the background\n const tickPromise = worker.tick();\n await sleep(25);\n\n // cancel while step is executing\n await handle.cancel();\n\n // wait for tick to complete\n await tickPromise;\n\n // step should have been executed but workflow should be canceled\n expect(stepExecuted).toBe(true);\n const canceled = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(canceled?.status).toBe(\"canceled\");\n });\n\n test(\"result() rejects for canceled workflows\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-result\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"1h\");\n return { completed: true };\n });\n\n const handle = await workflow.run();\n await handle.cancel();\n\n await expect(handle.result()).rejects.toThrow(/Workflow cancel-result was canceled/);\n });\n\n describe(\"version matching\", () => {\n test(\"worker matches workflow runs by version\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"versioned-workflow\", version: \"v1\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => \"v1-result\");\n });\n client.defineWorkflow({ name: \"versioned-workflow\", version: \"v2\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => \"v2-result\");\n });\n\n const worker = client.newWorker({ concurrency: 2 });\n\n const v1Spec = declareWorkflow({\n name: \"versioned-workflow\",\n version: \"v1\",\n });\n const v2Spec = declareWorkflow({\n name: \"versioned-workflow\",\n version: \"v2\",\n });\n\n const handleV1 = await client.runWorkflow(v1Spec);\n const handleV2 = await client.runWorkflow(v2Spec);\n\n await worker.tick();\n await sleep(100); // wait for background execution\n\n const resultV1 = await handleV1.result();\n const resultV2 = await handleV2.result();\n\n expect(resultV1).toBe(\"v1-result\");\n expect(resultV2).toBe(\"v2-result\");\n });\n\n test(\"worker fails workflow run when version is not registered\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-check\", version: \"v1\" }, () => \"v1-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-check\",\n version: \"v2\",\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-check\" (version: v2) is not registered',\n });\n });\n\n test(\"unversioned workflow does not match versioned run\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-mismatch\" }, () => \"unversioned-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-mismatch\",\n version: \"v1\",\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-mismatch\" (version: v1) is not registered',\n });\n });\n\n test(\"versioned workflow does not match unversioned run\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-required\", version: \"v1\" }, () => \"v1-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-required\",\n version: null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-required\" is not registered',\n });\n });\n\n test(\"workflow receives run's version, not registered version\", async () => {\n // this test verifies that the version passed to the workflow function\n // is the one from the workflow run, not the registered workflow\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"version-in-handler\", version: \"v1\" },\n async ({ version, step }) => {\n return await step.run({ name: \"get-version\" }, () => version);\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"v1\");\n });\n });\n});\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"names":["randomUUID","afterEach","beforeEach","describe","expect","test","declareWorkflow","OpenWorkflow","BackendPostgres","KNEX_GLOBAL_CONFIG","backend","connect","namespaceId","runMigrations","stop","client","workflow","defineWorkflow","name","input","worker","newWorker","payload","value","handle","run","tick","result","toEqual","toBe","executionCount","step","first","second","workflowRun","createWorkflowRun","workflowName","version","idempotencyKey","config","context","availableAt","deadlineAt","updated","getWorkflowRun","workflowRunId","id","status","error","toBeDefined","not","toBeNull","attemptCount","Error","String","success","attempts","sleep","executionOrder","push","executionTimes","start","Date","now","a","b","c","Promise","all","times","Object","values","maxTime","Math","max","minTime","min","toBeLessThan","concurrency","handles","completed","workerId","claimed","claimWorkflowRun","leaseDurationMs","claimedAgain","i","startTime","map","h","duration","executionCounts","stepA","stepB","stepC","stepCount","before","after","slept","delayMs","getTime","toBeGreaterThan","listStepAttempts","sleepStep","data","find","stepName","refreshedAttempts","completedSleepStep","step1Count","step2Count","failed","message","toContain","attempts1","attempts2","finalAttempts","length","every","sleeping","beforeSleepCount","afterSleepCount","worker1","workflowAfterFirst","attemptsAfterFirst","kind","worker2","cancel","finishedAt","canceled","rejects","toThrow","cancelWorkflowRun","stepExecuted","tickPromise","v1Spec","v2Spec","handleV1","runWorkflow","handleV2","resultV1","resultV2","ms","resolve","setTimeout"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/worker.test.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { afterEach, beforeEach, describe, expect, test } from \"vitest\";\nimport { declareWorkflow, OpenWorkflow } from \"./client\";\nimport { BackendPostgres } from \"./database/backend\";\nimport { KNEX_GLOBAL_CONFIG } from \"./testing/connection\";\n\ndescribe(\"Worker\", () => {\n let backend: BackendPostgres;\n\n beforeEach(async () => {\n backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n await backend.initialize();\n });\n\n afterEach(async () => {\n await backend.stop();\n });\n\n test(\"passes workflow input to handlers (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"context\" }, ({ input }) => input);\n const worker = client.newWorker();\n\n const payload = { value: 10 };\n const handle = await workflow.run(payload);\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual(payload);\n });\n\n test(\"processes workflow runs to completion (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"process\" },\n ({ input }: { input: { value: number } }) => input.value * 2,\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run({ value: 21 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(42);\n });\n\n test(\"step.run reuses cached results (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"cached-step\" }, async ({ step }) => {\n const first = await step.run({ name: \"once\" }, () => {\n executionCount++;\n return \"value\";\n });\n const second = await step.run({ name: \"once\" }, () => {\n executionCount++;\n return \"should-not-run\";\n });\n return { first, second };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ first: \"value\", second: \"value\" });\n expect(executionCount).toBe(1);\n });\n\n test(\"marks workflow for retry when definition is missing\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"missing\",\n version: null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n const worker = client.newWorker();\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toBeDefined();\n expect(updated?.availableAt).not.toBeNull();\n });\n\n test(\"retries failed workflows automatically (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let attemptCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"retry-test\" }, () => {\n attemptCount++;\n if (attemptCount < 2) {\n throw new Error(`Attempt ${String(attemptCount)} failed`);\n }\n return { success: true, attempts: attemptCount };\n });\n\n const worker = client.newWorker();\n\n // run the workflow\n const handle = await workflow.run();\n\n // first attempt - will fail and reschedule\n await worker.tick();\n await sleep(100); // wait for worker to finish\n expect(attemptCount).toBe(1);\n\n await sleep(1100); // wait for backoff delay\n\n // second attempt - will succeed\n await worker.tick();\n await sleep(100); // wait for worker to finish\n expect(attemptCount).toBe(2);\n\n const result = await handle.result();\n expect(result).toEqual({ success: true, attempts: 2 });\n });\n\n test(\"tick is a no-op when no work is available\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"noop\" }, () => null);\n const worker = client.newWorker();\n await worker.tick(); // no runs queued\n });\n\n test(\"handles step functions that return undefined (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"undefined-steps\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => {\n return; // explicit undefined\n });\n await step.run({ name: \"step-2\" }, () => {\n // implicit undefined\n });\n return { success: true };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ success: true });\n });\n\n test(\"executes steps synchronously within workflow (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionOrder: string[] = [];\n const workflow = client.defineWorkflow({ name: \"sync-steps\" }, async ({ step }) => {\n executionOrder.push(\"start\");\n await step.run({ name: \"step1\" }, () => {\n executionOrder.push(\"step1\");\n return 1;\n });\n executionOrder.push(\"between\");\n await step.run({ name: \"step2\" }, () => {\n executionOrder.push(\"step2\");\n return 2;\n });\n executionOrder.push(\"end\");\n return executionOrder;\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual([\"start\", \"step1\", \"between\", \"step2\", \"end\"]);\n });\n\n test(\"executes parallel steps with Promise.all (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionTimes: Record<string, number> = {};\n const workflow = client.defineWorkflow({ name: \"parallel\" }, async ({ step }) => {\n const start = Date.now();\n const [a, b, c] = await Promise.all([\n step.run({ name: \"step-a\" }, () => {\n executionTimes[\"step-a\"] = Date.now() - start;\n return \"a\";\n }),\n step.run({ name: \"step-b\" }, () => {\n executionTimes[\"step-b\"] = Date.now() - start;\n return \"b\";\n }),\n step.run({ name: \"step-c\" }, () => {\n executionTimes[\"step-c\"] = Date.now() - start;\n return \"c\";\n }),\n ]);\n return { a, b, c };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({ a: \"a\", b: \"b\", c: \"c\" });\n\n // steps should execute at roughly the same time (within 100ms)\n const times = Object.values(executionTimes);\n const maxTime = Math.max(...times);\n const minTime = Math.min(...times);\n expect(maxTime - minTime).toBeLessThan(100);\n });\n\n test(\"respects worker concurrency limit\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"concurrency-test\" }, () => {\n return \"done\";\n });\n\n const worker = client.newWorker({ concurrency: 2 });\n\n // create 5 workflow runs, though only 2 (concurrency limit) should be\n // completed per tick\n const handles = await Promise.all([\n workflow.run(),\n workflow.run(),\n workflow.run(),\n workflow.run(),\n workflow.run(),\n ]);\n\n await worker.tick();\n await sleep(100);\n\n let completed = 0;\n for (const handle of handles) {\n const run = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n if (run?.status === \"completed\") completed++;\n }\n\n expect(completed).toBe(2);\n });\n\n test(\"worker starts, processes work, and stops gracefully (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"lifecycle\" }, () => {\n return \"complete\";\n });\n\n const worker = client.newWorker();\n\n await worker.start();\n const handle = await workflow.run();\n await sleep(200);\n await worker.stop();\n\n const result = await handle.result();\n expect(result).toBe(\"complete\");\n });\n\n test(\"recovers from crashes during parallel step execution (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let attemptCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"crash-recovery\" }, async ({ step }) => {\n attemptCount++;\n\n const [a, b] = await Promise.all([\n step.run({ name: \"step-a\" }, () => {\n if (attemptCount > 1) return \"x\"; // should not happen since \"a\" will be cached\n return \"a\";\n }),\n step.run({ name: \"step-b\" }, () => {\n if (attemptCount === 1) throw new Error(\"Simulated crash\");\n return \"b\";\n }),\n ]);\n\n return { a, b, attempts: attemptCount };\n });\n\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n\n // first attempt will fail\n await worker.tick();\n await sleep(100);\n expect(attemptCount).toBe(1);\n\n // wait for backoff\n await sleep(1100);\n\n // second attempt should succeed\n await worker.tick();\n await sleep(100);\n\n const result = await handle.result();\n expect(result).toEqual({ a: \"a\", b: \"b\", attempts: 2 });\n expect(attemptCount).toBe(2);\n });\n\n test(\"reclaims workflow run when heartbeat stops (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"heartbeat-test\" }, () => \"done\");\n\n const handle = await workflow.run();\n const workerId = randomUUID();\n\n const claimed = await backend.claimWorkflowRun({\n workerId,\n leaseDurationMs: 50,\n });\n expect(claimed).not.toBeNull();\n\n // let lease expire before starting worker\n await sleep(100);\n\n // worker should be able to reclaim\n const worker = client.newWorker();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n });\n\n test(\"tick() returns count of claimed workflows\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"count-test\" }, () => \"result\");\n\n // enqueue 3 workflows\n await workflow.run();\n await workflow.run();\n await workflow.run();\n\n const worker = client.newWorker({ concurrency: 5 });\n\n // first tick should claim 3 workflows (all available)\n const claimed = await worker.tick();\n expect(claimed).toBe(3);\n\n // second tick should claim 0 (all already claimed)\n const claimedAgain = await worker.tick();\n expect(claimedAgain).toBe(0);\n\n await worker.stop();\n });\n\n test(\"tick() respects concurrency limit\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"concurrency-test\" }, async () => {\n await sleep(100);\n return \"done\";\n });\n\n // enqueue 10 workflows\n for (let i = 0; i < 10; i++) {\n await workflow.run();\n }\n\n const worker = client.newWorker({ concurrency: 3 });\n\n // first tick should claim exactly 3 (concurrency limit)\n const claimed = await worker.tick();\n expect(claimed).toBe(3);\n\n // second tick should claim 0 (all slots occupied)\n const claimedAgain = await worker.tick();\n expect(claimedAgain).toBe(0);\n\n await worker.stop();\n });\n\n test(\"worker only sleeps between claims when no work is available (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"adaptive-test\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => \"done\");\n return \"complete\";\n });\n\n // enqueue many workflows\n const handles = [];\n for (let i = 0; i < 20; i++) {\n handles.push(await workflow.run());\n }\n\n const worker = client.newWorker({ concurrency: 5 });\n\n const startTime = Date.now();\n await worker.start();\n\n // wait for all workflows to complete\n await Promise.all(handles.map((h) => h.result()));\n await worker.stop();\n\n const duration = Date.now() - startTime;\n\n // with this conditional sleep, all workflows should complete quickly\n // without it (with 100ms sleep between ticks), it would take much longer\n expect(duration).toBeLessThan(3000); // should complete in under 3 seconds\n });\n\n test(\"only failed steps re-execute on retry (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const executionCounts = {\n stepA: 0,\n stepB: 0,\n stepC: 0,\n };\n\n const workflow = client.defineWorkflow({ name: \"mixed-retry\" }, async ({ step }) => {\n const a = await step.run({ name: \"step-a\" }, () => {\n executionCounts.stepA++;\n return \"a-result\";\n });\n\n const b = await step.run({ name: \"step-b\" }, () => {\n executionCounts.stepB++;\n if (executionCounts.stepB === 1) {\n throw new Error(\"Step B fails on first attempt\");\n }\n return \"b-result\";\n });\n\n const c = await step.run({ name: \"step-c\" }, () => {\n executionCounts.stepC++;\n return \"c-result\";\n });\n\n return { a, b, c };\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first workflow attempt\n // - step-a succeeds\n // - step-b fails\n // - step-c never runs (workflow fails at step-b)\n await worker.tick();\n await sleep(100);\n expect(executionCounts.stepA).toBe(1);\n expect(executionCounts.stepB).toBe(1);\n expect(executionCounts.stepC).toBe(0);\n\n // wait for backoff\n await sleep(1100);\n\n // second workflow attempt\n // - step-a should be cached (not re-executed)\n // - step-b should be re-executed (failed previously)\n // - step-c should execute for first time\n await worker.tick();\n await sleep(100);\n expect(executionCounts.stepA).toBe(1); // still 1, was cached\n expect(executionCounts.stepB).toBe(2); // incremented, was retried\n expect(executionCounts.stepC).toBe(1); // incremented, first execution\n\n const result = await handle.result();\n expect(result).toEqual({\n a: \"a-result\",\n b: \"b-result\",\n c: \"c-result\",\n });\n });\n\n test(\"step.sleep postpones workflow execution (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let stepCount = 0;\n const workflow = client.defineWorkflow({ name: \"sleep-test\" }, async ({ step }) => {\n const before = await step.run({ name: \"before-sleep\" }, () => {\n stepCount++;\n return \"before\";\n });\n\n await step.sleep(\"pause\", \"100ms\");\n\n const after = await step.run({ name: \"after-sleep\" }, () => {\n stepCount++;\n return \"after\";\n });\n\n return { before, after };\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution - runs before-sleep, then sleeps\n await worker.tick();\n await sleep(50); // wait for processing\n expect(stepCount).toBe(1);\n\n // verify workflow was postponed with sleeping status\n const slept = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(slept?.status).toBe(\"sleeping\");\n expect(slept?.workerId).toBeNull(); // released during sleep\n expect(slept?.availableAt).not.toBeNull();\n if (!slept?.availableAt) throw new Error(\"availableAt should be set\");\n const delayMs = slept.availableAt.getTime() - Date.now();\n expect(delayMs).toBeGreaterThan(0);\n expect(delayMs).toBeLessThan(150); // should be ~100ms\n\n // verify sleep step is in \"running\" state during sleep\n const attempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const sleepStep = attempts.data.find((a) => a.stepName === \"pause\");\n expect(sleepStep?.status).toBe(\"running\");\n\n // wait for sleep duration\n await sleep(150);\n\n // second execution (after sleep)\n await worker.tick();\n await sleep(50); // wait for processing\n expect(stepCount).toBe(2);\n\n // verify sleep step is now \"completed\"\n const refreshedAttempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const completedSleepStep = refreshedAttempts.data.find((a) => a.stepName === \"pause\");\n expect(completedSleepStep?.status).toBe(\"completed\");\n\n const result = await handle.result();\n expect(result).toEqual({ before: \"before\", after: \"after\" });\n });\n\n test(\"step.sleep is cached on replay\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let step1Count = 0;\n let step2Count = 0;\n const workflow = client.defineWorkflow({ name: \"sleep-cache-test\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => {\n step1Count++;\n return \"one\";\n });\n\n // this should only postpone once\n await step.sleep(\"wait\", \"50ms\");\n\n await step.run({ name: \"step-2\" }, () => {\n step2Count++;\n return \"two\";\n });\n\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first attempt: execute step-1, then sleep (step-2 not executed)\n await worker.tick();\n await sleep(50);\n expect(step1Count).toBe(1);\n expect(step2Count).toBe(0);\n\n await sleep(100); // wait for sleep to complete\n\n // second attempt: step-1 is cached (not re-executed), sleep is cached, step-2 executes\n await worker.tick();\n await sleep(50);\n expect(step1Count).toBe(1); // still 1, was cached\n expect(step2Count).toBe(1); // now 1, executed after sleep\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n });\n\n test(\"step.sleep throws error for invalid duration format\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"invalid-duration\" }, async ({ step }) => {\n // @ts-expect-error - testing invalid duration\n await step.sleep(\"bad\", \"invalid\");\n return \"should-not-reach\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n await worker.tick();\n await sleep(100);\n\n const failed = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n\n expect(failed?.status).toBe(\"pending\"); // should be retrying\n expect(failed?.error).toBeDefined();\n expect(failed?.error?.message).toContain(\"Invalid duration format\");\n });\n\n test(\"step.sleep handles multiple sequential sleeps (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"sequential-sleeps\" }, async ({ step }) => {\n executionCount++;\n\n await step.run({ name: \"step-1\" }, () => \"one\");\n await step.sleep(\"sleep-1\", \"50ms\");\n await step.run({ name: \"step-2\" }, () => \"two\");\n await step.sleep(\"sleep-2\", \"50ms\");\n await step.run({ name: \"step-3\" }, () => \"three\");\n\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution: step-1, then sleep-1\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(1);\n\n // verify first sleep is running\n const attempts1 = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(attempts1.data.find((a) => a.stepName === \"sleep-1\")?.status).toBe(\"running\");\n\n // wait for first sleep\n await sleep(100);\n\n // second execution: sleep-1 completed, step-2, then sleep-2\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(2);\n\n // verify second sleep is running\n const attempts2 = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(attempts2.data.find((a) => a.stepName === \"sleep-1\")?.status).toBe(\"completed\");\n expect(attempts2.data.find((a) => a.stepName === \"sleep-2\")?.status).toBe(\"running\");\n\n // wait for second sleep\n await sleep(100);\n\n // third execution: sleep-2 completed, step-3, complete\n await worker.tick();\n await sleep(50);\n expect(executionCount).toBe(3);\n\n const result = await handle.result();\n expect(result).toBe(\"done\");\n\n // verify all steps completed\n const finalAttempts = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n expect(finalAttempts.data.length).toBe(5); // 3 regular steps + 2 sleeps\n expect(finalAttempts.data.every((a) => a.status === \"completed\")).toBe(true);\n });\n\n test(\"sleeping workflows can be claimed after availableAt\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"sleeping-claim-test\" }, async ({ step }) => {\n await step.run({ name: \"before\" }, () => \"before\");\n await step.sleep(\"wait\", \"100ms\");\n await step.run({ name: \"after\" }, () => \"after\");\n return \"done\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n\n // first execution - sleep\n await worker.tick();\n await sleep(50);\n\n // verify workflow is in sleeping state\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n expect(sleeping?.workerId).toBeNull();\n\n // wait for sleep duration\n await sleep(100);\n\n // verify workflow can be claimed again\n const claimed = await backend.claimWorkflowRun({\n workerId: \"test-worker\",\n leaseDurationMs: 30_000,\n });\n expect(claimed?.id).toBe(handle.workflowRun.id);\n expect(claimed?.status).toBe(\"running\");\n expect(claimed?.workerId).toBe(\"test-worker\");\n });\n\n test(\"sleep is not skipped when worker crashes after creating sleep step but before marking workflow as sleeping (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n let beforeSleepCount = 0;\n let afterSleepCount = 0;\n\n const workflow = client.defineWorkflow({ name: \"crash-during-sleep\" }, async ({ step }) => {\n executionCount++;\n\n await step.run({ name: \"before-sleep\" }, () => {\n beforeSleepCount++;\n return \"before\";\n });\n\n // this sleep should NOT be skipped even if crash happens\n await step.sleep(\"critical-pause\", \"200ms\");\n\n await step.run({ name: \"after-sleep\" }, () => {\n afterSleepCount++;\n return \"after\";\n });\n\n return { executionCount, beforeSleepCount, afterSleepCount };\n });\n\n const handle = await workflow.run();\n\n // first worker processes the workflow until sleep\n const worker1 = client.newWorker();\n await worker1.tick();\n await sleep(100);\n\n const workflowAfterFirst = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n\n expect(workflowAfterFirst?.status).toBe(\"sleeping\");\n\n const attemptsAfterFirst = await backend.listStepAttempts({\n workflowRunId: handle.workflowRun.id,\n });\n const sleepStep = attemptsAfterFirst.data.find((a) => a.stepName === \"critical-pause\");\n expect(sleepStep).toBeDefined();\n expect(sleepStep?.kind).toBe(\"sleep\");\n expect(sleepStep?.status).toBe(\"running\");\n\n await sleep(50); // only 50ms of the 200ms sleep\n\n // if there's a running sleep step, the workflow should be properly\n // transitioned to sleeping\n const worker2 = client.newWorker();\n await worker2.tick();\n\n // after-sleep step should NOT have executed yet\n expect(afterSleepCount).toBe(0);\n\n // wait for the full sleep duration to elapse then check to make sure\n // workflow is claimable and resume\n await sleep(200);\n await worker2.tick();\n await sleep(100);\n expect(afterSleepCount).toBe(1);\n const result = await handle.result();\n expect(result.afterSleepCount).toBe(1);\n });\n\n test(\"version enables conditional code paths (known slow test)\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"conditional-workflow\", version: \"v2\" },\n async ({ version, step }) => {\n return version === \"v1\"\n ? await step.run({ name: \"old-step\" }, () => \"old-logic\")\n : await step.run({ name: \"new-step\" }, () => \"new-logic\");\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"new-logic\");\n });\n\n test(\"workflow version is null when not specified\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"unversioned-workflow\" },\n async ({ version, step }) => {\n const result = await step.run({ name: \"check-version\" }, () => {\n return { version };\n });\n return result;\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result.version).toBeNull();\n });\n\n test(\"cancels a pending workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-pending\" }, async ({ step }) => {\n await step.run({ name: \"step-1\" }, () => \"result\");\n return { completed: true };\n });\n\n const handle = await workflow.run();\n\n // cancel before worker processes it\n await handle.cancel();\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"canceled\");\n expect(workflowRun?.finishedAt).not.toBeNull();\n expect(workflowRun?.availableAt).toBeNull();\n expect(workflowRun?.workerId).toBeNull();\n });\n\n test(\"cancels a sleeping workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-sleeping\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"1h\");\n return { completed: true };\n });\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n // cancel while sleeping\n await handle.cancel();\n\n const canceled = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(canceled?.status).toBe(\"canceled\");\n expect(canceled?.finishedAt).not.toBeNull();\n expect(canceled?.availableAt).toBeNull();\n expect(canceled?.workerId).toBeNull();\n });\n\n test(\"cannot cancel a completed workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-completed\" }, () => ({\n completed: true,\n }));\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result.completed).toBe(true);\n\n // try to cancel after success\n await expect(handle.cancel()).rejects.toThrow(\n /Cannot cancel workflow run .* with status completed/,\n );\n });\n\n test(\"cannot cancel a failed workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-failed\" }, () => {\n throw new Error(\"intentional failure\");\n });\n const worker = client.newWorker();\n\n const handle = await workflow.run({ value: 1 }, { deadlineAt: new Date() });\n await worker.tick();\n\n // wait for it to fail due to deadline\n await sleep(100);\n\n const failed = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(failed?.status).toBe(\"failed\");\n\n // try to cancel after failure\n await expect(handle.cancel()).rejects.toThrow(\n /Cannot cancel workflow run .* with status failed/,\n );\n });\n\n test(\"cannot cancel non-existent workflow\", async () => {\n await expect(\n backend.cancelWorkflowRun({\n workflowRunId: \"non-existent-id\",\n }),\n ).rejects.toThrow(/Workflow run non-existent-id does not exist/);\n });\n\n test(\"worker handles when canceled workflow during execution\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let stepExecuted = false;\n const workflow = client.defineWorkflow(\n { name: \"cancel-during-execution\" },\n async ({ step }) => {\n await step.run({ name: \"step-1\" }, async () => {\n stepExecuted = true;\n // simulate some work\n await sleep(50);\n return \"result\";\n });\n return { completed: true };\n },\n );\n const worker = client.newWorker();\n\n const handle = await workflow.run();\n\n // start processing in the background\n const tickPromise = worker.tick();\n await sleep(25);\n\n // cancel while step is executing\n await handle.cancel();\n\n // wait for tick to complete\n await tickPromise;\n\n // step should have been executed but workflow should be canceled\n expect(stepExecuted).toBe(true);\n const canceled = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(canceled?.status).toBe(\"canceled\");\n });\n\n test(\"result() rejects for canceled workflows\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"cancel-result\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"1h\");\n return { completed: true };\n });\n\n const handle = await workflow.run();\n await handle.cancel();\n\n await expect(handle.result()).rejects.toThrow(/Workflow cancel-result was canceled/);\n });\n\n describe(\"version matching\", () => {\n test(\"worker matches workflow runs by version\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"versioned-workflow\", version: \"v1\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => \"v1-result\");\n });\n client.defineWorkflow({ name: \"versioned-workflow\", version: \"v2\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => \"v2-result\");\n });\n\n const worker = client.newWorker({ concurrency: 2 });\n\n const v1Spec = declareWorkflow({\n name: \"versioned-workflow\",\n version: \"v1\",\n });\n const v2Spec = declareWorkflow({\n name: \"versioned-workflow\",\n version: \"v2\",\n });\n\n const handleV1 = await client.runWorkflow(v1Spec);\n const handleV2 = await client.runWorkflow(v2Spec);\n\n await worker.tick();\n await sleep(100); // wait for background execution\n\n const resultV1 = await handleV1.result();\n const resultV2 = await handleV2.result();\n\n expect(resultV1).toBe(\"v1-result\");\n expect(resultV2).toBe(\"v2-result\");\n });\n\n test(\"worker fails workflow run when version is not registered\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-check\", version: \"v1\" }, () => \"v1-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-check\",\n version: \"v2\",\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-check\" (version: v2) is not registered',\n });\n });\n\n test(\"unversioned workflow does not match versioned run\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-mismatch\" }, () => \"unversioned-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-mismatch\",\n version: \"v1\",\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-mismatch\" (version: v1) is not registered',\n });\n });\n\n test(\"versioned workflow does not match unversioned run\", async () => {\n const client = new OpenWorkflow({ backend });\n\n client.defineWorkflow({ name: \"version-required\", version: \"v1\" }, () => \"v1-result\");\n\n const worker = client.newWorker();\n\n const workflowRun = await backend.createWorkflowRun({\n workflowName: \"version-required\",\n version: null,\n idempotencyKey: null,\n config: {},\n context: null,\n input: null,\n availableAt: null,\n deadlineAt: null,\n });\n\n await worker.tick();\n\n const updated = await backend.getWorkflowRun({\n workflowRunId: workflowRun.id,\n });\n\n expect(updated?.status).toBe(\"pending\");\n expect(updated?.error).toEqual({\n message: 'Workflow \"version-required\" is not registered',\n });\n });\n\n test(\"workflow receives run's version, not registered version\", async () => {\n // this test verifies that the version passed to the workflow function\n // is the one from the workflow run, not the registered workflow\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"version-in-handler\", version: \"v1\" },\n async ({ version, step }) => {\n return await step.run({ name: \"get-version\" }, () => version);\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run();\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"v1\");\n });\n });\n});\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"names":["randomUUID","afterEach","beforeEach","describe","expect","test","declareWorkflow","OpenWorkflow","BackendPostgres","KNEX_GLOBAL_CONFIG","backend","namespaceId","runMigrations","initialize","stop","client","workflow","defineWorkflow","name","input","worker","newWorker","payload","value","handle","run","tick","result","toEqual","toBe","executionCount","step","first","second","workflowRun","createWorkflowRun","workflowName","version","idempotencyKey","config","context","availableAt","deadlineAt","updated","getWorkflowRun","workflowRunId","id","status","error","toBeDefined","not","toBeNull","attemptCount","Error","String","success","attempts","sleep","executionOrder","push","executionTimes","start","Date","now","a","b","c","Promise","all","times","Object","values","maxTime","Math","max","minTime","min","toBeLessThan","concurrency","handles","completed","workerId","claimed","claimWorkflowRun","leaseDurationMs","claimedAgain","i","startTime","map","h","duration","executionCounts","stepA","stepB","stepC","stepCount","before","after","slept","delayMs","getTime","toBeGreaterThan","listStepAttempts","sleepStep","data","find","stepName","refreshedAttempts","completedSleepStep","step1Count","step2Count","failed","message","toContain","attempts1","attempts2","finalAttempts","length","every","sleeping","beforeSleepCount","afterSleepCount","worker1","workflowAfterFirst","attemptsAfterFirst","kind","worker2","cancel","finishedAt","canceled","rejects","toThrow","cancelWorkflowRun","stepExecuted","tickPromise","v1Spec","v2Spec","handleV1","runWorkflow","handleV2","resultV1","resultV2","ms","resolve","setTimeout"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonamu-kit/tasks",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Sonamu Task - Simple & Distributed Task Queue",
6
6
  "main": "./dist/index.js",
@@ -34,17 +34,19 @@
34
34
  "c12": "^3.3.2"
35
35
  },
36
36
  "devDependencies": {
37
- "@biomejs/biome": "^2.3.7",
37
+ "@types/inflection": "^2.0.0",
38
+ "@biomejs/biome": "^2.3.10",
38
39
  "@swc/cli": "^0.7.8",
39
- "@swc/core": "^1.15.3",
40
- "@types/node": "^24.9.2",
40
+ "@swc/core": "^1.13.5",
41
+ "@types/node": "25.0.3",
41
42
  "nodemon": "^3.1.10",
42
43
  "tsx": "^4.20.6",
43
44
  "typescript": "^5.9.3",
44
45
  "vitest": "^4.0.10"
45
46
  },
46
47
  "peerDependencies": {
47
- "knex": "^3.1.0"
48
+ "knex": "^3.1.0",
49
+ "@logtape/logtape": "1.3.5"
48
50
  },
49
51
  "optionalDependencies": {
50
52
  "pg-native": "^3.5.2"
@@ -1,11 +1,8 @@
1
- import knex from "knex";
2
1
  import { DEFAULT_SCHEMA, migrate } from "../src/database/base";
3
2
  import { KNEX_GLOBAL_CONFIG } from "../src/testing/connection";
4
3
 
5
4
  async function main() {
6
- const knexInstance = knex(KNEX_GLOBAL_CONFIG);
7
- await migrate(knexInstance, DEFAULT_SCHEMA);
8
- await knexInstance.destroy();
5
+ await migrate(KNEX_GLOBAL_CONFIG, DEFAULT_SCHEMA);
9
6
  }
10
7
 
11
8
  main();
@@ -9,10 +9,11 @@ describe("OpenWorkflow", () => {
9
9
  let backend: BackendPostgres;
10
10
 
11
11
  beforeEach(async () => {
12
- backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
12
+ backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
13
13
  namespaceId: randomUUID(),
14
14
  runMigrations: false,
15
15
  });
16
+ await backend.initialize();
16
17
  });
17
18
 
18
19
  afterEach(async () => {
package/src/client.ts CHANGED
@@ -184,7 +184,6 @@ export class OpenWorkflow {
184
184
  * Declare a workflow without providing its implementation (which is provided
185
185
  * separately via `implementWorkflow`). Returns a lightweight WorkflowSpec
186
186
  * that can be used to schedule workflow runs.
187
- * @param config - Workflow config
188
187
  * @param spec - Workflow spec
189
188
  * @returns Workflow spec
190
189
  * @example
@@ -14,7 +14,7 @@ type UnitAnyCase = Capitalize<Unit> | Uppercase<Unit> | Lowercase<Unit>;
14
14
  export type DurationString = `${number}` | `${number}${UnitAnyCase}` | `${number} ${UnitAnyCase}`;
15
15
 
16
16
  /**
17
- * Parse a duration string into milliseconds. Exmaples:
17
+ * Parse a duration string into milliseconds. Examples:
18
18
  * - short units: "1ms", "5s", "30m", "2h", "7d", "3w", "1y"
19
19
  * - long units: "1 millisecond", "5 seconds", "30 minutes", "2 hours", "7 days", "3 weeks", "1 year"
20
20
  * @param str - Duration string
@@ -116,7 +116,8 @@ export async function validateInput<RunInput, Input>(
116
116
  /**
117
117
  * Check if a workflow run status represents a terminal state.
118
118
  * @param status - The workflow run status
119
- * @returns True if the status is terminal (completed, failed, or canceled)
119
+ * @returns True if the status is terminal (succeeded, completed, failed, or canceled).
120
+ * Note: 'succeeded' is deprecated in favor of 'completed'.
120
121
  */
121
122
  export function isTerminalStatus(
122
123
  status: string,
@@ -5,10 +5,12 @@ import { testBackend } from "./backend.testsuite";
5
5
 
6
6
  testBackend({
7
7
  setup: async () => {
8
- return await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
8
+ const backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
9
9
  namespaceId: randomUUID(),
10
10
  runMigrations: false,
11
11
  });
12
+ await backend.initialize();
13
+ return backend;
12
14
  },
13
15
  teardown: async (backend) => {
14
16
  await (backend as BackendPostgres).stop();