@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
@@ -44,9 +44,15 @@ export class PostgresPubSub {
44
44
  }
45
45
  // destroy the listener and close the connection, do not destroy the knex connection
46
46
  async destroy() {
47
- this._destroyed = true;
48
- this._connection.off("close", this._onClosed);
49
- await this.knex.client.destroyRawConnection(this._connection);
47
+ if (this._destroyed) {
48
+ return;
49
+ }
50
+ try {
51
+ this._connection.off("close", this._onClosed);
52
+ await this.knex.client.destroyRawConnection(this._connection);
53
+ } finally{
54
+ this._destroyed = true;
55
+ }
50
56
  }
51
57
  // create a new listener and connect to the database
52
58
  static async create(knex) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/database/pubsub.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { Knex } from \"knex\";\nimport { err, ok, type Result } from \"../core/result\";\n\nexport type OnSubscribed = (result: Result<string | null>) => void | Promise<void>;\n\nexport class PostgresPubSub {\n private _destroyed = false;\n private _onClosed: () => Promise<void>;\n private _listeners = new Map<string, Set<OnSubscribed>>();\n\n // biome-ignore lint/suspicious/noExplicitAny: Knex exposes a connection as any\n private _connection: any | null = null;\n\n private constructor(private readonly knex: Knex) {\n // Re-connect to the database when the connection is closed and not destroyed manually\n this._onClosed = (async () => {\n if (this._destroyed) {\n return;\n }\n\n await this.connect();\n }).bind(this);\n }\n\n get destroyed() {\n return this._destroyed;\n }\n\n // acquire new raw connection and set up listeners\n async connect() {\n const connection = await this.knex.client.acquireRawConnection();\n connection.on(\"close\", this._onClosed);\n connection.on(\n \"notification\",\n async ({ channel, payload: rawPayload }: { channel: string; payload: unknown }) => {\n const payload =\n typeof rawPayload === \"string\" && rawPayload.length !== 0 ? rawPayload : null;\n const listeners = this._listeners.get(channel);\n if (!listeners) {\n return;\n }\n\n const result = ok(payload);\n await Promise.allSettled(\n Array.from(listeners.values()).map((listener) => Promise.resolve(listener(result))),\n );\n },\n );\n connection.on(\"error\", async (error: Error) => {\n const result = err(error);\n await Promise.allSettled(\n Array.from(this._listeners.values())\n .flatMap((listeners) => Array.from(listeners))\n .map((listener) => Promise.resolve(listener(result))),\n );\n });\n\n for (const channel of this._listeners.keys()) {\n connection.query(`LISTEN ${channel}`);\n }\n\n this._connection = connection;\n }\n\n // destroy the listener and close the connection, do not destroy the knex connection\n async destroy() {\n this._destroyed = true;\n this._connection.off(\"close\", this._onClosed);\n await this.knex.client.destroyRawConnection(this._connection);\n }\n\n // create a new listener and connect to the database\n static async create(knex: Knex) {\n const listener = new PostgresPubSub(knex);\n await listener.connect();\n return listener;\n }\n\n // add a new listener to the channel\n listenEvent(channel: string, callback: OnSubscribed) {\n if (!this._listeners.has(channel)) {\n this._connection?.query(`LISTEN ${channel}`);\n this._listeners.set(channel, new Set<OnSubscribed>().add(callback));\n return;\n }\n\n const listeners = this._listeners.get(channel);\n assert(listeners, \"Listener channel not found\");\n listeners.add(callback);\n }\n}\n"],"names":["assert","err","ok","PostgresPubSub","_destroyed","_onClosed","_listeners","Map","_connection","knex","connect","bind","destroyed","connection","client","acquireRawConnection","on","channel","payload","rawPayload","length","listeners","get","result","Promise","allSettled","Array","from","values","map","listener","resolve","error","flatMap","keys","query","destroy","off","destroyRawConnection","create","listenEvent","callback","has","set","Set","add"],"mappings":"AAAA,OAAOA,YAAY,SAAS;AAE5B,SAASC,GAAG,EAAEC,EAAE,QAAqB,oBAAiB;AAItD,OAAO,MAAMC;;IACHC,aAAa,MAAM;IACnBC,UAA+B;IAC/BC,aAAa,IAAIC,MAAiC;IAE1D,+EAA+E;IACvEC,cAA0B,KAAK;IAEvC,YAAoB,AAAiBC,IAAU,CAAE;aAAZA,OAAAA;QACnC,sFAAsF;QACtF,IAAI,CAACJ,SAAS,GAAG,AAAC,CAAA;YAChB,IAAI,IAAI,CAACD,UAAU,EAAE;gBACnB;YACF;YAEA,MAAM,IAAI,CAACM,OAAO;QACpB,CAAA,EAAGC,IAAI,CAAC,IAAI;IACd;IAEA,IAAIC,YAAY;QACd,OAAO,IAAI,CAACR,UAAU;IACxB;IAEA,kDAAkD;IAClD,MAAMM,UAAU;QACd,MAAMG,aAAa,MAAM,IAAI,CAACJ,IAAI,CAACK,MAAM,CAACC,oBAAoB;QAC9DF,WAAWG,EAAE,CAAC,SAAS,IAAI,CAACX,SAAS;QACrCQ,WAAWG,EAAE,CACX,gBACA,OAAO,EAAEC,OAAO,EAAEC,SAASC,UAAU,EAAyC;YAC5E,MAAMD,UACJ,OAAOC,eAAe,YAAYA,WAAWC,MAAM,KAAK,IAAID,aAAa;YAC3E,MAAME,YAAY,IAAI,CAACf,UAAU,CAACgB,GAAG,CAACL;YACtC,IAAI,CAACI,WAAW;gBACd;YACF;YAEA,MAAME,SAASrB,GAAGgB;YAClB,MAAMM,QAAQC,UAAU,CACtBC,MAAMC,IAAI,CAACN,UAAUO,MAAM,IAAIC,GAAG,CAAC,CAACC,WAAaN,QAAQO,OAAO,CAACD,SAASP;QAE9E;QAEFV,WAAWG,EAAE,CAAC,SAAS,OAAOgB;YAC5B,MAAMT,SAAStB,IAAI+B;YACnB,MAAMR,QAAQC,UAAU,CACtBC,MAAMC,IAAI,CAAC,IAAI,CAACrB,UAAU,CAACsB,MAAM,IAC9BK,OAAO,CAAC,CAACZ,YAAcK,MAAMC,IAAI,CAACN,YAClCQ,GAAG,CAAC,CAACC,WAAaN,QAAQO,OAAO,CAACD,SAASP;QAElD;QAEA,KAAK,MAAMN,WAAW,IAAI,CAACX,UAAU,CAAC4B,IAAI,GAAI;YAC5CrB,WAAWsB,KAAK,CAAC,CAAC,OAAO,EAAElB,SAAS;QACtC;QAEA,IAAI,CAACT,WAAW,GAAGK;IACrB;IAEA,oFAAoF;IACpF,MAAMuB,UAAU;QACd,IAAI,CAAChC,UAAU,GAAG;QAClB,IAAI,CAACI,WAAW,CAAC6B,GAAG,CAAC,SAAS,IAAI,CAAChC,SAAS;QAC5C,MAAM,IAAI,CAACI,IAAI,CAACK,MAAM,CAACwB,oBAAoB,CAAC,IAAI,CAAC9B,WAAW;IAC9D;IAEA,oDAAoD;IACpD,aAAa+B,OAAO9B,IAAU,EAAE;QAC9B,MAAMqB,WAAW,IAAI3B,eAAeM;QACpC,MAAMqB,SAASpB,OAAO;QACtB,OAAOoB;IACT;IAEA,oCAAoC;IACpCU,YAAYvB,OAAe,EAAEwB,QAAsB,EAAE;QACnD,IAAI,CAAC,IAAI,CAACnC,UAAU,CAACoC,GAAG,CAACzB,UAAU;YACjC,IAAI,CAACT,WAAW,EAAE2B,MAAM,CAAC,OAAO,EAAElB,SAAS;YAC3C,IAAI,CAACX,UAAU,CAACqC,GAAG,CAAC1B,SAAS,IAAI2B,MAAoBC,GAAG,CAACJ;YACzD;QACF;QAEA,MAAMpB,YAAY,IAAI,CAACf,UAAU,CAACgB,GAAG,CAACL;QACtCjB,OAAOqB,WAAW;QAClBA,UAAUwB,GAAG,CAACJ;IAChB;AACF"}
1
+ {"version":3,"sources":["../../src/database/pubsub.ts"],"sourcesContent":["import assert from \"assert\";\nimport type { Knex } from \"knex\";\nimport { err, ok, type Result } from \"../core/result\";\n\nexport type OnSubscribed = (result: Result<string | null>) => void | Promise<void>;\n\nexport class PostgresPubSub {\n private _destroyed = false;\n private _onClosed: () => Promise<void>;\n private _listeners = new Map<string, Set<OnSubscribed>>();\n\n // biome-ignore lint/suspicious/noExplicitAny: Knex exposes a connection as any\n private _connection: any | null = null;\n\n private constructor(private readonly knex: Knex) {\n // Re-connect to the database when the connection is closed and not destroyed manually\n this._onClosed = (async () => {\n if (this._destroyed) {\n return;\n }\n\n await this.connect();\n }).bind(this);\n }\n\n get destroyed() {\n return this._destroyed;\n }\n\n // acquire new raw connection and set up listeners\n async connect() {\n const connection = await this.knex.client.acquireRawConnection();\n connection.on(\"close\", this._onClosed);\n connection.on(\n \"notification\",\n async ({ channel, payload: rawPayload }: { channel: string; payload: unknown }) => {\n const payload =\n typeof rawPayload === \"string\" && rawPayload.length !== 0 ? rawPayload : null;\n const listeners = this._listeners.get(channel);\n if (!listeners) {\n return;\n }\n\n const result = ok(payload);\n await Promise.allSettled(\n Array.from(listeners.values()).map((listener) => Promise.resolve(listener(result))),\n );\n },\n );\n connection.on(\"error\", async (error: Error) => {\n const result = err(error);\n await Promise.allSettled(\n Array.from(this._listeners.values())\n .flatMap((listeners) => Array.from(listeners))\n .map((listener) => Promise.resolve(listener(result))),\n );\n });\n\n for (const channel of this._listeners.keys()) {\n connection.query(`LISTEN ${channel}`);\n }\n\n this._connection = connection;\n }\n\n // destroy the listener and close the connection, do not destroy the knex connection\n async destroy() {\n if (this._destroyed) {\n return;\n }\n try {\n this._connection.off(\"close\", this._onClosed);\n await this.knex.client.destroyRawConnection(this._connection);\n } finally {\n this._destroyed = true;\n }\n }\n\n // create a new listener and connect to the database\n static async create(knex: Knex) {\n const listener = new PostgresPubSub(knex);\n await listener.connect();\n return listener;\n }\n\n // add a new listener to the channel\n listenEvent(channel: string, callback: OnSubscribed) {\n if (!this._listeners.has(channel)) {\n this._connection?.query(`LISTEN ${channel}`);\n this._listeners.set(channel, new Set<OnSubscribed>().add(callback));\n return;\n }\n\n const listeners = this._listeners.get(channel);\n assert(listeners, \"Listener channel not found\");\n listeners.add(callback);\n }\n}\n"],"names":["assert","err","ok","PostgresPubSub","_destroyed","_onClosed","_listeners","Map","_connection","knex","connect","bind","destroyed","connection","client","acquireRawConnection","on","channel","payload","rawPayload","length","listeners","get","result","Promise","allSettled","Array","from","values","map","listener","resolve","error","flatMap","keys","query","destroy","off","destroyRawConnection","create","listenEvent","callback","has","set","Set","add"],"mappings":"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"}
@@ -6,10 +6,11 @@ import { KNEX_GLOBAL_CONFIG } from "./testing/connection.js";
6
6
  describe("StepExecutor", ()=>{
7
7
  let backend;
8
8
  beforeAll(async ()=>{
9
- backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
9
+ backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
10
10
  namespaceId: randomUUID(),
11
11
  runMigrations: false
12
12
  });
13
+ await backend.initialize();
13
14
  });
14
15
  afterAll(async ()=>{
15
16
  await backend.stop();
@@ -178,10 +179,11 @@ describe("StepExecutor", ()=>{
178
179
  describe("executeWorkflow", ()=>{
179
180
  let backend;
180
181
  beforeAll(async ()=>{
181
- backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
182
+ backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
182
183
  namespaceId: randomUUID(),
183
184
  runMigrations: false
184
185
  });
186
+ await backend.initialize();
185
187
  });
186
188
  afterAll(async ()=>{
187
189
  await backend.stop();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/execution.test.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { afterAll, beforeAll, describe, expect, test } from \"vitest\";\nimport { BackendPostgres } from \".\";\nimport { OpenWorkflow } from \"./client\";\nimport { KNEX_GLOBAL_CONFIG } from \"./testing/connection\";\n\ndescribe(\"StepExecutor\", () => {\n let backend: BackendPostgres;\n\n beforeAll(async () => {\n backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n });\n\n afterAll(async () => {\n await backend.stop();\n });\n\n test(\"executes step and returns result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-basic\" }, async ({ step }) => {\n const result = await step.run({ name: \"add\" }, () => 5 + 3);\n return result;\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(8);\n });\n\n test(\"caches step results for same step name\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"executor-cached\" }, async ({ step }) => {\n const first = await step.run({ name: \"cached-step\" }, () => {\n executionCount++;\n return \"first-execution\";\n });\n const second = await step.run({ name: \"cached-step\" }, () => {\n executionCount++;\n return \"second-execution\";\n });\n return { first, second };\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).toEqual({\n first: \"first-execution\",\n second: \"first-execution\",\n });\n expect(executionCount).toBe(1);\n });\n\n test(\"different step names execute independently\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow(\n { name: \"executor-different-steps\" },\n async ({ step }) => {\n const first = await step.run({ name: \"step-1\" }, () => {\n executionCount++;\n return \"a\";\n });\n const second = await step.run({ name: \"step-2\" }, () => {\n executionCount++;\n return \"b\";\n });\n return { first, second };\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).toEqual({ first: \"a\", second: \"b\" });\n expect(executionCount).toBe(2);\n });\n\n test(\"propagates step errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-error\" }, async ({ step }) => {\n await step.run({ name: \"failing-step\" }, () => {\n throw new Error(\"Step failed intentionally\");\n });\n return \"should not reach\";\n });\n\n const worker = client.newWorker();\n // Use deadline to force immediate failure without retries\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"sleep puts workflow in sleeping status\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-sleep\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"5s\");\n return \"after sleep\";\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n await worker.tick();\n await sleep(50); // Wait for sleep step to complete\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"sleeping\");\n expect(workflowRun?.availableAt).not.toBeNull();\n });\n\n test(\"workflow resumes after sleep duration\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"resume-after-sleep\" }, async ({ step }) => {\n const value = await step.run({ name: \"before\" }, () => 5);\n await step.sleep(\"wait\", \"10ms\");\n return value + 10;\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n\n // First tick - hits sleep\n await worker.tick();\n await sleep(50); // Wait for tick to complete\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n\n // Wait for sleep to elapse\n await sleep(50);\n\n // Second tick - completes\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n});\n\ndescribe(\"executeWorkflow\", () => {\n let backend: BackendPostgres;\n\n beforeAll(async () => {\n backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n });\n\n afterAll(async () => {\n await backend.stop();\n });\n\n describe(\"successful execution\", () => {\n test(\"executes a simple workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"simple-workflow\" },\n ({ input }: { input: { a: number; b: number } }) => {\n return input.a + input.b;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ a: 10, b: 5 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n\n test(\"executes a multi-step workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow<{ value: number }, number>(\n { name: \"multi-step-workflow\" },\n async ({ input, step }) => {\n const sum = await step.run({ name: \"add\" }, () => input.value + 5);\n const product = await step.run({ name: \"multiply\" }, () => sum * 2);\n return product;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ value: 10 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(30);\n });\n\n test(\"returns null for workflows without return\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"void-workflow\" }, () => null);\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).toBeNull();\n });\n\n test(\"returns null from workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"null-workflow\" }, () => null);\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).toBeNull();\n });\n });\n\n describe(\"error handling\", () => {\n test(\"handles workflow errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"failing-workflow\" }, () => {\n throw new Error(\"Workflow error\");\n });\n\n const worker = client.newWorker();\n // Use deadline to skip retries - fails with deadline exceeded\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"handles step errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"step-error-workflow\" }, async ({ step }) => {\n await step.run({ name: \"failing\" }, () => {\n throw new Error(\"Step error\");\n });\n return \"unreachable\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"serializes non-Error exceptions\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"non-error-workflow\" }, async ({ step }) => {\n await step.run({ name: \"throw-object\" }, () => {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw { custom: \"error\", code: 500 };\n });\n return \"nope\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow();\n });\n });\n\n describe(\"sleep handling\", () => {\n test(\"workflow enters sleeping status\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"sleep-workflow\" }, async ({ step }) => {\n await step.sleep(\"wait\", \"5s\");\n return \"after sleep\";\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n await worker.tick();\n await sleep(50); // Wait for sleep step to complete\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"sleeping\");\n });\n\n test(\"resumes workflow after sleep duration\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow<{ value: number }, number>(\n { name: \"resume-after-sleep\" },\n async ({ input, step }) => {\n const sum = await step.run({ name: \"add\" }, () => input.value + 1);\n await step.sleep(\"wait\", \"10ms\");\n return sum + 10;\n },\n );\n\n const handle = await workflow.run({ value: 5 });\n const worker = client.newWorker();\n\n // first tick - hits sleep\n await worker.tick();\n await sleep(50);\n\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n\n // wait for sleep\n await sleep(50);\n\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(16);\n });\n });\n\n describe(\"workflow with complex data\", () => {\n test(\"handles objects as input and output\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"user-workflow\" },\n ({ input }: { input: { name: string; age: number } }) => {\n return {\n greeting: `Hello, ${input.name}! You are ${String(input.age)} years old.`,\n processed: true,\n };\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ name: \"Alice\", age: 30 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({\n greeting: \"Hello, Alice! You are 30 years old.\",\n processed: true,\n });\n });\n\n test(\"handles arrays in workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"array-workflow\" },\n ({ input }: { input: { numbers: number[] } }) => {\n return input.numbers.reduce((a, b) => a + b, 0);\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ numbers: [1, 2, 3, 4, 5] });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n });\n\n describe(\"result type handling\", () => {\n test(\"returns success with numeric result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"numeric-result\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => 100 + 200);\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(300);\n });\n\n test(\"returns success with string result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"string-result\" },\n ({ input }: { input: { text: string } }) => {\n return input.text.toUpperCase();\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ text: \"hello world\" });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"HELLO WORLD\");\n });\n\n test(\"returns success with boolean result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"bool-result\" },\n ({ input }: { input: { value: number } }) => {\n return input.value > 0;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ value: 42 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(true);\n });\n });\n\n describe(\"step execution order\", () => {\n test(\"executes steps in sequence\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const order: string[] = [];\n const workflow = client.defineWorkflow({ name: \"sequence-workflow\" }, async ({ step }) => {\n await step.run({ name: \"first\" }, () => order.push(\"first\"));\n await step.run({ name: \"second\" }, () => order.push(\"second\"));\n await step.run({ name: \"third\" }, () => order.push(\"third\"));\n return order;\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).toEqual([\"first\", \"second\", \"third\"]);\n });\n });\n\n describe(\"version handling\", () => {\n test(\"passes version to workflow function\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"version-workflow\", version: \"1.0.0\" },\n ({ version }) => {\n return { receivedVersion: 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).toEqual({ receivedVersion: \"1.0.0\" });\n });\n\n test(\"passes null version when not specified\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"no-version-workflow\" }, ({ version }) => {\n return { receivedVersion: version };\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).toEqual({ receivedVersion: null });\n });\n });\n});\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"names":["randomUUID","afterAll","beforeAll","describe","expect","test","BackendPostgres","OpenWorkflow","KNEX_GLOBAL_CONFIG","backend","connect","namespaceId","runMigrations","stop","client","workflow","defineWorkflow","name","step","result","run","worker","newWorker","handle","tick","toBe","executionCount","first","second","toEqual","Error","deadlineAt","Date","sleep","rejects","toThrow","workflowRun","getWorkflowRun","workflowRunId","id","status","availableAt","not","toBeNull","value","sleeping","input","a","b","sum","product","custom","code","greeting","String","age","processed","numbers","reduce","text","toUpperCase","order","push","version","receivedVersion","ms","Promise","resolve","setTimeout"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/execution.test.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { afterAll, beforeAll, describe, expect, test } from \"vitest\";\nimport { BackendPostgres } from \".\";\nimport { OpenWorkflow } from \"./client\";\nimport { KNEX_GLOBAL_CONFIG } from \"./testing/connection\";\n\ndescribe(\"StepExecutor\", () => {\n let backend: BackendPostgres;\n\n beforeAll(async () => {\n backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n await backend.initialize();\n });\n\n afterAll(async () => {\n await backend.stop();\n });\n\n test(\"executes step and returns result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-basic\" }, async ({ step }) => {\n const result = await step.run({ name: \"add\" }, () => 5 + 3);\n return result;\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(8);\n });\n\n test(\"caches step results for same step name\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow({ name: \"executor-cached\" }, async ({ step }) => {\n const first = await step.run({ name: \"cached-step\" }, () => {\n executionCount++;\n return \"first-execution\";\n });\n const second = await step.run({ name: \"cached-step\" }, () => {\n executionCount++;\n return \"second-execution\";\n });\n return { first, second };\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).toEqual({\n first: \"first-execution\",\n second: \"first-execution\",\n });\n expect(executionCount).toBe(1);\n });\n\n test(\"different step names execute independently\", async () => {\n const client = new OpenWorkflow({ backend });\n\n let executionCount = 0;\n const workflow = client.defineWorkflow(\n { name: \"executor-different-steps\" },\n async ({ step }) => {\n const first = await step.run({ name: \"step-1\" }, () => {\n executionCount++;\n return \"a\";\n });\n const second = await step.run({ name: \"step-2\" }, () => {\n executionCount++;\n return \"b\";\n });\n return { first, second };\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).toEqual({ first: \"a\", second: \"b\" });\n expect(executionCount).toBe(2);\n });\n\n test(\"propagates step errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-error\" }, async ({ step }) => {\n await step.run({ name: \"failing-step\" }, () => {\n throw new Error(\"Step failed intentionally\");\n });\n return \"should not reach\";\n });\n\n const worker = client.newWorker();\n // Use deadline to force immediate failure without retries\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"sleep puts workflow in sleeping status\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"executor-sleep\" }, async ({ step }) => {\n await step.sleep(\"sleep-1\", \"5s\");\n return \"after sleep\";\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n await worker.tick();\n await sleep(50); // Wait for sleep step to complete\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"sleeping\");\n expect(workflowRun?.availableAt).not.toBeNull();\n });\n\n test(\"workflow resumes after sleep duration\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"resume-after-sleep\" }, async ({ step }) => {\n const value = await step.run({ name: \"before\" }, () => 5);\n await step.sleep(\"wait\", \"10ms\");\n return value + 10;\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n\n // First tick - hits sleep\n await worker.tick();\n await sleep(50); // Wait for tick to complete\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n\n // Wait for sleep to elapse\n await sleep(50);\n\n // Second tick - completes\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n});\n\ndescribe(\"executeWorkflow\", () => {\n let backend: BackendPostgres;\n\n beforeAll(async () => {\n backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n await backend.initialize();\n });\n\n afterAll(async () => {\n await backend.stop();\n });\n\n describe(\"successful execution\", () => {\n test(\"executes a simple workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"simple-workflow\" },\n ({ input }: { input: { a: number; b: number } }) => {\n return input.a + input.b;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ a: 10, b: 5 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n\n test(\"executes a multi-step workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow<{ value: number }, number>(\n { name: \"multi-step-workflow\" },\n async ({ input, step }) => {\n const sum = await step.run({ name: \"add\" }, () => input.value + 5);\n const product = await step.run({ name: \"multiply\" }, () => sum * 2);\n return product;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ value: 10 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(30);\n });\n\n test(\"returns null for workflows without return\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"void-workflow\" }, () => null);\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).toBeNull();\n });\n\n test(\"returns null from workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"null-workflow\" }, () => null);\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).toBeNull();\n });\n });\n\n describe(\"error handling\", () => {\n test(\"handles workflow errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"failing-workflow\" }, () => {\n throw new Error(\"Workflow error\");\n });\n\n const worker = client.newWorker();\n // Use deadline to skip retries - fails with deadline exceeded\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"handles step errors with deadline exceeded\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"step-error-workflow\" }, async ({ step }) => {\n await step.run({ name: \"failing\" }, () => {\n throw new Error(\"Step error\");\n });\n return \"unreachable\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow(/deadline exceeded/);\n });\n\n test(\"serializes non-Error exceptions\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"non-error-workflow\" }, async ({ step }) => {\n await step.run({ name: \"throw-object\" }, () => {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw { custom: \"error\", code: 500 };\n });\n return \"nope\";\n });\n\n const worker = client.newWorker();\n const handle = await workflow.run({}, { deadlineAt: new Date() });\n await worker.tick();\n await sleep(100);\n\n await expect(handle.result()).rejects.toThrow();\n });\n });\n\n describe(\"sleep handling\", () => {\n test(\"workflow enters sleeping status\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"sleep-workflow\" }, async ({ step }) => {\n await step.sleep(\"wait\", \"5s\");\n return \"after sleep\";\n });\n\n const handle = await workflow.run();\n const worker = client.newWorker();\n await worker.tick();\n await sleep(50); // Wait for sleep step to complete\n\n const workflowRun = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(workflowRun?.status).toBe(\"sleeping\");\n });\n\n test(\"resumes workflow after sleep duration\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow<{ value: number }, number>(\n { name: \"resume-after-sleep\" },\n async ({ input, step }) => {\n const sum = await step.run({ name: \"add\" }, () => input.value + 1);\n await step.sleep(\"wait\", \"10ms\");\n return sum + 10;\n },\n );\n\n const handle = await workflow.run({ value: 5 });\n const worker = client.newWorker();\n\n // first tick - hits sleep\n await worker.tick();\n await sleep(50);\n\n const sleeping = await backend.getWorkflowRun({\n workflowRunId: handle.workflowRun.id,\n });\n expect(sleeping?.status).toBe(\"sleeping\");\n\n // wait for sleep\n await sleep(50);\n\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(16);\n });\n });\n\n describe(\"workflow with complex data\", () => {\n test(\"handles objects as input and output\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"user-workflow\" },\n ({ input }: { input: { name: string; age: number } }) => {\n return {\n greeting: `Hello, ${input.name}! You are ${String(input.age)} years old.`,\n processed: true,\n };\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ name: \"Alice\", age: 30 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toEqual({\n greeting: \"Hello, Alice! You are 30 years old.\",\n processed: true,\n });\n });\n\n test(\"handles arrays in workflow\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"array-workflow\" },\n ({ input }: { input: { numbers: number[] } }) => {\n return input.numbers.reduce((a, b) => a + b, 0);\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ numbers: [1, 2, 3, 4, 5] });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(15);\n });\n });\n\n describe(\"result type handling\", () => {\n test(\"returns success with numeric result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"numeric-result\" }, async ({ step }) => {\n return await step.run({ name: \"compute\" }, () => 100 + 200);\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(300);\n });\n\n test(\"returns success with string result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"string-result\" },\n ({ input }: { input: { text: string } }) => {\n return input.text.toUpperCase();\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ text: \"hello world\" });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(\"HELLO WORLD\");\n });\n\n test(\"returns success with boolean result\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"bool-result\" },\n ({ input }: { input: { value: number } }) => {\n return input.value > 0;\n },\n );\n\n const worker = client.newWorker();\n const handle = await workflow.run({ value: 42 });\n await worker.tick();\n\n const result = await handle.result();\n expect(result).toBe(true);\n });\n });\n\n describe(\"step execution order\", () => {\n test(\"executes steps in sequence\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const order: string[] = [];\n const workflow = client.defineWorkflow({ name: \"sequence-workflow\" }, async ({ step }) => {\n await step.run({ name: \"first\" }, () => order.push(\"first\"));\n await step.run({ name: \"second\" }, () => order.push(\"second\"));\n await step.run({ name: \"third\" }, () => order.push(\"third\"));\n return order;\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).toEqual([\"first\", \"second\", \"third\"]);\n });\n });\n\n describe(\"version handling\", () => {\n test(\"passes version to workflow function\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow(\n { name: \"version-workflow\", version: \"1.0.0\" },\n ({ version }) => {\n return { receivedVersion: 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).toEqual({ receivedVersion: \"1.0.0\" });\n });\n\n test(\"passes null version when not specified\", async () => {\n const client = new OpenWorkflow({ backend });\n\n const workflow = client.defineWorkflow({ name: \"no-version-workflow\" }, ({ version }) => {\n return { receivedVersion: version };\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).toEqual({ receivedVersion: null });\n });\n });\n});\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"],"names":["randomUUID","afterAll","beforeAll","describe","expect","test","BackendPostgres","OpenWorkflow","KNEX_GLOBAL_CONFIG","backend","namespaceId","runMigrations","initialize","stop","client","workflow","defineWorkflow","name","step","result","run","worker","newWorker","handle","tick","toBe","executionCount","first","second","toEqual","Error","deadlineAt","Date","sleep","rejects","toThrow","workflowRun","getWorkflowRun","workflowRunId","id","status","availableAt","not","toBeNull","value","sleeping","input","a","b","sum","product","custom","code","greeting","String","age","processed","numbers","reduce","text","toUpperCase","order","push","version","receivedVersion","ms","Promise","resolve","setTimeout"],"mappings":"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"}
@@ -7,10 +7,11 @@ async function getBackend() {
7
7
  if (_backend !== null) {
8
8
  return _backend;
9
9
  }
10
- _backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
10
+ _backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
11
11
  runMigrations: true,
12
12
  namespaceId: randomUUID()
13
13
  });
14
+ await _backend.initialize();
14
15
  return _backend;
15
16
  }
16
17
  async function practice() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/practices/01-remote-workflow.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { randomUUID } from \"node:crypto\";\nimport { BackendPostgres, OpenWorkflow } from \"../\";\nimport { KNEX_GLOBAL_CONFIG } from \"../testing/connection\";\n\nlet _backend: BackendPostgres | null = null;\n\nasync function getBackend(): Promise<BackendPostgres> {\n if (_backend !== null) {\n return _backend;\n }\n\n _backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {\n runMigrations: true,\n namespaceId: randomUUID(),\n });\n\n return _backend;\n}\n\nasync function practice() {\n const backend = await getBackend();\n const ow = new OpenWorkflow({ backend });\n\n const sampleWorkflow = ow.defineWorkflow({ name: \"sample-workflow\" }, async ({ step }) => {\n const { result: result1 } = await step.run({ name: \"test-1\" }, async () => {\n return {\n result: [\"Result from test-1\"],\n };\n });\n\n await step.run({ name: \"test-2\" }, async () => {\n return await new Promise<void>((resolve) => setTimeout(resolve, 1000));\n });\n\n return await step.run({ name: \"test-3\" }, async () => {\n return {\n result: [...result1, \"Result from test-3\"],\n };\n });\n });\n\n // create a worker that will listen to the channel and process the workflow runs\n const worker = ow.newWorker({ concurrency: 3 });\n await worker.start();\n\n const handle = await sampleWorkflow.run();\n\n await new Promise((resolve) => setTimeout(resolve, 3000));\n await worker.tick();\n\n const result = await handle.result();\n assert.deepEqual(result, {\n result: [\"Result from test-1\", \"Result from test-3\"],\n });\n\n await worker.stop();\n await backend.stop();\n}\n\nawait practice();\n"],"names":["assert","randomUUID","BackendPostgres","OpenWorkflow","KNEX_GLOBAL_CONFIG","_backend","getBackend","connect","runMigrations","namespaceId","practice","backend","ow","sampleWorkflow","defineWorkflow","name","step","result","result1","run","Promise","resolve","setTimeout","worker","newWorker","concurrency","start","handle","tick","deepEqual","stop"],"mappings":"AAAA,OAAOA,YAAY,cAAc;AACjC,SAASC,UAAU,QAAQ,cAAc;AACzC,SAASC,eAAe,EAAEC,YAAY,QAAQ,cAAM;AACpD,SAASC,kBAAkB,QAAQ,2BAAwB;AAE3D,IAAIC,WAAmC;AAEvC,eAAeC;IACb,IAAID,aAAa,MAAM;QACrB,OAAOA;IACT;IAEAA,WAAW,MAAMH,gBAAgBK,OAAO,CAACH,oBAAoB;QAC3DI,eAAe;QACfC,aAAaR;IACf;IAEA,OAAOI;AACT;AAEA,eAAeK;IACb,MAAMC,UAAU,MAAML;IACtB,MAAMM,KAAK,IAAIT,aAAa;QAAEQ;IAAQ;IAEtC,MAAME,iBAAiBD,GAAGE,cAAc,CAAC;QAAEC,MAAM;IAAkB,GAAG,OAAO,EAAEC,IAAI,EAAE;QACnF,MAAM,EAAEC,QAAQC,OAAO,EAAE,GAAG,MAAMF,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YAC7D,OAAO;gBACLE,QAAQ;oBAAC;iBAAqB;YAChC;QACF;QAEA,MAAMD,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YACjC,OAAO,MAAM,IAAIK,QAAc,CAACC,UAAYC,WAAWD,SAAS;QAClE;QAEA,OAAO,MAAML,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YACxC,OAAO;gBACLE,QAAQ;uBAAIC;oBAAS;iBAAqB;YAC5C;QACF;IACF;IAEA,gFAAgF;IAChF,MAAMK,SAASX,GAAGY,SAAS,CAAC;QAAEC,aAAa;IAAE;IAC7C,MAAMF,OAAOG,KAAK;IAElB,MAAMC,SAAS,MAAMd,eAAeM,GAAG;IAEvC,MAAM,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAAS;IACnD,MAAME,OAAOK,IAAI;IAEjB,MAAMX,SAAS,MAAMU,OAAOV,MAAM;IAClCjB,OAAO6B,SAAS,CAACZ,QAAQ;QACvBA,QAAQ;YAAC;YAAsB;SAAqB;IACtD;IAEA,MAAMM,OAAOO,IAAI;IACjB,MAAMnB,QAAQmB,IAAI;AACpB;AAEA,MAAMpB"}
1
+ {"version":3,"sources":["../../src/practices/01-remote-workflow.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { randomUUID } from \"node:crypto\";\nimport { BackendPostgres, OpenWorkflow } from \"../\";\nimport { KNEX_GLOBAL_CONFIG } from \"../testing/connection\";\n\nlet _backend: BackendPostgres | null = null;\n\nasync function getBackend(): Promise<BackendPostgres> {\n if (_backend !== null) {\n return _backend;\n }\n\n _backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {\n runMigrations: true,\n namespaceId: randomUUID(),\n });\n\n await _backend.initialize();\n return _backend;\n}\n\nasync function practice() {\n const backend = await getBackend();\n const ow = new OpenWorkflow({ backend });\n\n const sampleWorkflow = ow.defineWorkflow({ name: \"sample-workflow\" }, async ({ step }) => {\n const { result: result1 } = await step.run({ name: \"test-1\" }, async () => {\n return {\n result: [\"Result from test-1\"],\n };\n });\n\n await step.run({ name: \"test-2\" }, async () => {\n return await new Promise<void>((resolve) => setTimeout(resolve, 1000));\n });\n\n return await step.run({ name: \"test-3\" }, async () => {\n return {\n result: [...result1, \"Result from test-3\"],\n };\n });\n });\n\n // create a worker that will listen to the channel and process the workflow runs\n const worker = ow.newWorker({ concurrency: 3 });\n await worker.start();\n\n const handle = await sampleWorkflow.run();\n\n await new Promise((resolve) => setTimeout(resolve, 3000));\n await worker.tick();\n\n const result = await handle.result();\n assert.deepEqual(result, {\n result: [\"Result from test-1\", \"Result from test-3\"],\n });\n\n await worker.stop();\n await backend.stop();\n}\n\nawait practice();\n"],"names":["assert","randomUUID","BackendPostgres","OpenWorkflow","KNEX_GLOBAL_CONFIG","_backend","getBackend","runMigrations","namespaceId","initialize","practice","backend","ow","sampleWorkflow","defineWorkflow","name","step","result","result1","run","Promise","resolve","setTimeout","worker","newWorker","concurrency","start","handle","tick","deepEqual","stop"],"mappings":"AAAA,OAAOA,YAAY,cAAc;AACjC,SAASC,UAAU,QAAQ,cAAc;AACzC,SAASC,eAAe,EAAEC,YAAY,QAAQ,cAAM;AACpD,SAASC,kBAAkB,QAAQ,2BAAwB;AAE3D,IAAIC,WAAmC;AAEvC,eAAeC;IACb,IAAID,aAAa,MAAM;QACrB,OAAOA;IACT;IAEAA,WAAW,IAAIH,gBAAgBE,oBAAoB;QACjDG,eAAe;QACfC,aAAaP;IACf;IAEA,MAAMI,SAASI,UAAU;IACzB,OAAOJ;AACT;AAEA,eAAeK;IACb,MAAMC,UAAU,MAAML;IACtB,MAAMM,KAAK,IAAIT,aAAa;QAAEQ;IAAQ;IAEtC,MAAME,iBAAiBD,GAAGE,cAAc,CAAC;QAAEC,MAAM;IAAkB,GAAG,OAAO,EAAEC,IAAI,EAAE;QACnF,MAAM,EAAEC,QAAQC,OAAO,EAAE,GAAG,MAAMF,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YAC7D,OAAO;gBACLE,QAAQ;oBAAC;iBAAqB;YAChC;QACF;QAEA,MAAMD,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YACjC,OAAO,MAAM,IAAIK,QAAc,CAACC,UAAYC,WAAWD,SAAS;QAClE;QAEA,OAAO,MAAML,KAAKG,GAAG,CAAC;YAAEJ,MAAM;QAAS,GAAG;YACxC,OAAO;gBACLE,QAAQ;uBAAIC;oBAAS;iBAAqB;YAC5C;QACF;IACF;IAEA,gFAAgF;IAChF,MAAMK,SAASX,GAAGY,SAAS,CAAC;QAAEC,aAAa;IAAE;IAC7C,MAAMF,OAAOG,KAAK;IAElB,MAAMC,SAAS,MAAMd,eAAeM,GAAG;IAEvC,MAAM,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAAS;IACnD,MAAME,OAAOK,IAAI;IAEjB,MAAMX,SAAS,MAAMU,OAAOV,MAAM;IAClCjB,OAAO6B,SAAS,CAACZ,QAAQ;QACvBA,QAAQ;YAAC;YAAsB;SAAqB;IACtD;IAEA,MAAMM,OAAOO,IAAI;IACjB,MAAMnB,QAAQmB,IAAI;AACpB;AAEA,MAAMpB"}
@@ -1,4 +1,4 @@
1
- import { type Knex } from "knex";
1
+ import type { Knex } from "knex";
2
2
  import { BackendPostgres } from "../database/backend";
3
3
  export declare const KNEX_GLOBAL_CONFIG: Knex.Config;
4
4
  export declare function migrate(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/testing/connection.ts"],"names":[],"mappings":"AACA,OAAa,EAAE,KAAK,IAAI,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKtD,eAAO,MAAM,kBAAkB,EAAE,IAAI,CAAC,MAY5B,CAAC;AAEX,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAU9D;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjD"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/testing/connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKtD,eAAO,MAAM,kBAAkB,EAAE,IAAI,CAAC,MAY5B,CAAC;AAEX,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC,CAY9D;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAMjD"}
@@ -1,5 +1,4 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import knex from "knex";
3
2
  import { BackendPostgres } from "../database/backend.js";
4
3
  import { migrate as baseMigrate, DEFAULT_SCHEMA } from "../database/base.js";
5
4
  let backend = null;
@@ -17,15 +16,17 @@ export const KNEX_GLOBAL_CONFIG = {
17
16
  }
18
17
  };
19
18
  export async function migrate() {
20
- await baseMigrate(knex(KNEX_GLOBAL_CONFIG), DEFAULT_SCHEMA);
19
+ await baseMigrate(KNEX_GLOBAL_CONFIG, DEFAULT_SCHEMA);
21
20
  }
22
21
  export async function createBackend() {
23
22
  if (backend) {
24
23
  return backend;
25
24
  }
26
- backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
27
- namespaceId: randomUUID()
25
+ backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
26
+ namespaceId: randomUUID(),
27
+ runMigrations: false
28
28
  });
29
+ await backend.initialize();
29
30
  return backend;
30
31
  }
31
32
  export async function stopBackend() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/testing/connection.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport knex, { type Knex } from \"knex\";\nimport { BackendPostgres } from \"../database/backend\";\nimport { migrate as baseMigrate, DEFAULT_SCHEMA } from \"../database/base\";\n\nlet backend: BackendPostgres | null = null;\n\nexport const KNEX_GLOBAL_CONFIG: Knex.Config = {\n client: \"pg\",\n connection: {\n host: \"127.0.0.1\",\n port: 5432,\n user: \"postgres\",\n password: \"miomock123\",\n database: \"postgres\",\n },\n pool: {\n max: 50,\n },\n} as const;\n\nexport async function migrate(): Promise<void> {\n await baseMigrate(knex(KNEX_GLOBAL_CONFIG), DEFAULT_SCHEMA);\n}\n\nexport async function createBackend(): Promise<BackendPostgres> {\n if (backend) {\n return backend;\n }\n\n backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n });\n\n return backend;\n}\n\nexport async function stopBackend(): Promise<void> {\n if (backend) {\n await backend.stop();\n }\n\n backend = null;\n}\n"],"names":["randomUUID","knex","BackendPostgres","migrate","baseMigrate","DEFAULT_SCHEMA","backend","KNEX_GLOBAL_CONFIG","client","connection","host","port","user","password","database","pool","max","createBackend","connect","namespaceId","stopBackend","stop"],"mappings":"AAAA,SAASA,UAAU,QAAQ,cAAc;AACzC,OAAOC,UAAyB,OAAO;AACvC,SAASC,eAAe,QAAQ,yBAAsB;AACtD,SAASC,WAAWC,WAAW,EAAEC,cAAc,QAAQ,sBAAmB;AAE1E,IAAIC,UAAkC;AAEtC,OAAO,MAAMC,qBAAkC;IAC7CC,QAAQ;IACRC,YAAY;QACVC,MAAM;QACNC,MAAM;QACNC,MAAM;QACNC,UAAU;QACVC,UAAU;IACZ;IACAC,MAAM;QACJC,KAAK;IACP;AACF,EAAW;AAEX,OAAO,eAAeb;IACpB,MAAMC,YAAYH,KAAKM,qBAAqBF;AAC9C;AAEA,OAAO,eAAeY;IACpB,IAAIX,SAAS;QACX,OAAOA;IACT;IAEAA,UAAU,MAAMJ,gBAAgBgB,OAAO,CAACX,oBAAoB;QAC1DY,aAAanB;IACf;IAEA,OAAOM;AACT;AAEA,OAAO,eAAec;IACpB,IAAId,SAAS;QACX,MAAMA,QAAQe,IAAI;IACpB;IAEAf,UAAU;AACZ"}
1
+ {"version":3,"sources":["../../src/testing/connection.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Knex } from \"knex\";\nimport { BackendPostgres } from \"../database/backend\";\nimport { migrate as baseMigrate, DEFAULT_SCHEMA } from \"../database/base\";\n\nlet backend: BackendPostgres | null = null;\n\nexport const KNEX_GLOBAL_CONFIG: Knex.Config = {\n client: \"pg\",\n connection: {\n host: \"127.0.0.1\",\n port: 5432,\n user: \"postgres\",\n password: \"miomock123\",\n database: \"postgres\",\n },\n pool: {\n max: 50,\n },\n} as const;\n\nexport async function migrate(): Promise<void> {\n await baseMigrate(KNEX_GLOBAL_CONFIG, DEFAULT_SCHEMA);\n}\n\nexport async function createBackend(): Promise<BackendPostgres> {\n if (backend) {\n return backend;\n }\n\n backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {\n namespaceId: randomUUID(),\n runMigrations: false,\n });\n await backend.initialize();\n\n return backend;\n}\n\nexport async function stopBackend(): Promise<void> {\n if (backend) {\n await backend.stop();\n }\n\n backend = null;\n}\n"],"names":["randomUUID","BackendPostgres","migrate","baseMigrate","DEFAULT_SCHEMA","backend","KNEX_GLOBAL_CONFIG","client","connection","host","port","user","password","database","pool","max","createBackend","namespaceId","runMigrations","initialize","stopBackend","stop"],"mappings":"AAAA,SAASA,UAAU,QAAQ,cAAc;AAEzC,SAASC,eAAe,QAAQ,yBAAsB;AACtD,SAASC,WAAWC,WAAW,EAAEC,cAAc,QAAQ,sBAAmB;AAE1E,IAAIC,UAAkC;AAEtC,OAAO,MAAMC,qBAAkC;IAC7CC,QAAQ;IACRC,YAAY;QACVC,MAAM;QACNC,MAAM;QACNC,MAAM;QACNC,UAAU;QACVC,UAAU;IACZ;IACAC,MAAM;QACJC,KAAK;IACP;AACF,EAAW;AAEX,OAAO,eAAeb;IACpB,MAAMC,YAAYG,oBAAoBF;AACxC;AAEA,OAAO,eAAeY;IACpB,IAAIX,SAAS;QACX,OAAOA;IACT;IAEAA,UAAU,IAAIJ,gBAAgBK,oBAAoB;QAChDW,aAAajB;QACbkB,eAAe;IACjB;IACA,MAAMb,QAAQc,UAAU;IAExB,OAAOd;AACT;AAEA,OAAO,eAAee;IACpB,IAAIf,SAAS;QACX,MAAMA,QAAQgB,IAAI;IACpB;IAEAhB,UAAU;AACZ"}
@@ -6,10 +6,11 @@ import { KNEX_GLOBAL_CONFIG } from "./testing/connection.js";
6
6
  describe("Worker", ()=>{
7
7
  let backend;
8
8
  beforeEach(async ()=>{
9
- backend = await BackendPostgres.connect(KNEX_GLOBAL_CONFIG, {
9
+ backend = new BackendPostgres(KNEX_GLOBAL_CONFIG, {
10
10
  namespaceId: randomUUID(),
11
11
  runMigrations: false
12
12
  });
13
+ await backend.initialize();
13
14
  });
14
15
  afterEach(async ()=>{
15
16
  await backend.stop();