@dudousxd/nestjs-durable-core 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/backoff.d.ts +5 -0
  2. package/dist/backoff.d.ts.map +1 -0
  3. package/dist/backoff.js +14 -0
  4. package/dist/backoff.js.map +1 -0
  5. package/dist/checkpoints.d.ts +17 -0
  6. package/dist/checkpoints.d.ts.map +1 -0
  7. package/dist/checkpoints.js +28 -0
  8. package/dist/checkpoints.js.map +1 -0
  9. package/dist/completion.d.ts +15 -0
  10. package/dist/completion.d.ts.map +1 -0
  11. package/dist/completion.js +13 -0
  12. package/dist/completion.js.map +1 -0
  13. package/dist/engine.d.ts +117 -10
  14. package/dist/engine.d.ts.map +1 -1
  15. package/dist/engine.js +287 -276
  16. package/dist/engine.js.map +1 -1
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/interfaces.d.ts +113 -17
  22. package/dist/interfaces.d.ts.map +1 -1
  23. package/dist/protocol.d.ts +3 -0
  24. package/dist/protocol.d.ts.map +1 -1
  25. package/dist/protocol.js +13 -1
  26. package/dist/protocol.js.map +1 -1
  27. package/dist/queue.d.ts +48 -0
  28. package/dist/queue.d.ts.map +1 -0
  29. package/dist/queue.js +45 -0
  30. package/dist/queue.js.map +1 -0
  31. package/dist/scheduler.d.ts +22 -7
  32. package/dist/scheduler.d.ts.map +1 -1
  33. package/dist/scheduler.js +40 -6
  34. package/dist/scheduler.js.map +1 -1
  35. package/dist/testing/in-memory-transport.d.ts +6 -4
  36. package/dist/testing/in-memory-transport.d.ts.map +1 -1
  37. package/dist/testing/in-memory-transport.js +4 -2
  38. package/dist/testing/in-memory-transport.js.map +1 -1
  39. package/dist/transport-pool.d.ts +23 -0
  40. package/dist/transport-pool.d.ts.map +1 -0
  41. package/dist/transport-pool.js +54 -0
  42. package/dist/transport-pool.js.map +1 -0
  43. package/dist/workflow-ctx.d.ts +46 -0
  44. package/dist/workflow-ctx.d.ts.map +1 -0
  45. package/dist/workflow-ctx.js +260 -0
  46. package/dist/workflow-ctx.js.map +1 -0
  47. package/package.json +8 -1
package/dist/scheduler.js CHANGED
@@ -1,21 +1,55 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.scheduledRunId = scheduledRunId;
4
+ exports.prevCronFireMs = prevCronFireMs;
4
5
  exports.runSchedules = runSchedules;
5
- /** Deterministic run id for a schedule's current time window — stable within that window. */
6
+ /** Deterministic run id for a fixed-interval schedule's current time window. */
6
7
  function scheduledRunId(key, everyMs, nowMs) {
7
8
  return `sched:${key}:${Math.floor(nowMs / everyMs)}`;
8
9
  }
10
+ let cronParser;
11
+ function loadCronParser() {
12
+ if (cronParser)
13
+ return cronParser;
14
+ try {
15
+ // Lazy + optional: core stays dependency-free; only users who schedule by cron need this.
16
+ cronParser = require('cron-parser');
17
+ }
18
+ catch {
19
+ throw new Error('cron schedules need the optional peer dependency "cron-parser" — install it (e.g. `npm i cron-parser`).');
20
+ }
21
+ return cronParser;
22
+ }
23
+ /**
24
+ * Epoch ms of the most recent cron fire at or before `nowMs`, evaluated in `timezone` (default UTC).
25
+ * This is the deterministic "bucket" a cron run is keyed on, so polling repeatedly within an
26
+ * interval resolves to the same fire time — and thus the same idempotent run id.
27
+ */
28
+ function prevCronFireMs(expr, nowMs, timezone = 'UTC') {
29
+ const parser = loadCronParser();
30
+ // `+1` makes a fire landing exactly on `nowMs` count as "at or before now", not the prior one.
31
+ const it = parser.parseExpression(expr, { currentDate: new Date(nowMs + 1), tz: timezone });
32
+ return it.prev().toDate().getTime();
33
+ }
34
+ /** The deterministic, idempotent run id for a schedule at `nowMs` — its current fire window. */
35
+ function scheduleRunIdAt(s, nowMs) {
36
+ if (s.cron != null)
37
+ return `sched:${s.key}:${prevCronFireMs(s.cron, nowMs, s.timezone)}`;
38
+ if (s.everyMs != null)
39
+ return scheduledRunId(s.key, s.everyMs, nowMs);
40
+ throw new Error(`schedule "${s.key}" needs either "everyMs" or "cron"`);
41
+ }
9
42
  /**
10
- * Start each schedule's current-window run. The run id is the time bucket and `engine.start` is
11
- * idempotent, so firing this on an interval — or racing two instances on the same tick — starts
12
- * **each window exactly once**. Wire it to a `setInterval`, the durable timer poller, or
13
- * `@nestjs/schedule`. Returns the run ids for the current windows.
43
+ * Start each schedule's current-window run. The run id is the time bucket (a fixed-interval index,
44
+ * or the cron fire time) and `engine.start` is idempotent, so firing this on an interval — or
45
+ * racing two instances on the same tick — starts **each window exactly once**. Wire it to a
46
+ * `setInterval`, the durable timer poller, or `@nestjs/schedule`. Returns the run ids for the
47
+ * current windows.
14
48
  */
15
49
  async function runSchedules(engine, schedules, nowMs) {
16
50
  const ids = [];
17
51
  for (const s of schedules) {
18
- const runId = scheduledRunId(s.key, s.everyMs, nowMs);
52
+ const runId = scheduleRunIdAt(s, nowMs);
19
53
  await engine.start(s.workflow, s.input, runId);
20
54
  ids.push(runId);
21
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":";;AAYA,wCAEC;AAQD,oCAYC;AAvBD,6FAA6F;AAC7F,SAAgB,cAAc,CAAC,GAAW,EAAE,OAAe,EAAE,KAAa;IACxE,OAAO,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,YAAY,CAChC,MAAqC,EACrC,SAAuC,EACvC,KAAa;IAEb,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtD,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":";;AAoBA,wCAEC;AAsBD,wCAKC;AAgBD,oCAYC;AA1DD,gFAAgF;AAChF,SAAgB,cAAc,CAAC,GAAW,EAAE,OAAe,EAAE,KAAa;IACxE,OAAO,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC;AACvD,CAAC;AAGD,IAAI,UAAkC,CAAC;AACvC,SAAS,cAAc;IACrB,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,IAAI,CAAC;QACH,0FAA0F;QAC1F,UAAU,GAAG,OAAO,CAAC,aAAa,CAAe,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,yGAAyG,CAC1G,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,KAAa,EAAE,QAAQ,GAAG,KAAK;IAC1E,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,+FAA+F;IAC/F,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5F,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC;AACtC,CAAC;AAED,gGAAgG;AAChG,SAAS,eAAe,CAAC,CAAoB,EAAE,KAAa;IAC1D,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC,CAAC,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IACzF,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI;QAAE,OAAO,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACtE,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,GAAG,oCAAoC,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,YAAY,CAChC,MAAqC,EACrC,SAAuC,EACvC,KAAa;IAEb,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,10 +1,12 @@
1
- import type { ControlMessage, Heartbeat, RemoteTask, StepResult, Transport } from '../interfaces';
1
+ import type { ControlMessage, ControlPlane, Heartbeat, RemoteTask, StepResult, Transport } from '../interfaces';
2
2
  import { type StepHandler } from '../protocol';
3
3
  /**
4
- * An in-process `Transport` for tests and local development: registered handlers stand in
5
- * for remote workers, so a whole cross-app workflow runs in a single process.
4
+ * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered
5
+ * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,
6
+ * and control messages broadcast locally. Pass the same instance as both `transport` and
7
+ * `controlPlane`.
6
8
  */
7
- export declare class InMemoryTransport implements Transport {
9
+ export declare class InMemoryTransport implements Transport, ControlPlane {
8
10
  private readonly handlers;
9
11
  private resultHandler?;
10
12
  private readonly controlHandlers;
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-transport.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,aAAa,CAAC;AAE/D;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,aAAa,CAAC,CAAwC;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI;IAIrC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9D,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAMzD,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;CAGxD"}
1
+ {"version":3,"file":"in-memory-transport.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,WAAW,EAAkB,MAAM,aAAa,CAAC;AAE/D;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,SAAS,EAAE,YAAY;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,aAAa,CAAC,CAAwC;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4C;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI;IAIrC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/C,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI9D,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAMzD,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;CAGxD"}
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InMemoryTransport = void 0;
4
4
  const protocol_1 = require("../protocol");
5
5
  /**
6
- * An in-process `Transport` for tests and local development: registered handlers stand in
7
- * for remote workers, so a whole cross-app workflow runs in a single process.
6
+ * An in-process `Transport` (and `ControlPlane`) for tests and local development: registered
7
+ * handlers stand in for remote workers, so a whole cross-app workflow runs in a single process,
8
+ * and control messages broadcast locally. Pass the same instance as both `transport` and
9
+ * `controlPlane`.
8
10
  */
9
11
  class InMemoryTransport {
10
12
  handlers = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-transport.js","sourceRoot":"","sources":["../../src/testing/in-memory-transport.ts"],"names":[],"mappings":";;;AACA,0CAA+D;AAE/D;;;GAGG;AACH,MAAa,iBAAiB;IACX,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IACnD,aAAa,CAAyC;IAC7C,eAAe,GAAG,IAAI,GAAG,EAAiC,CAAC;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAY,EAAE,EAAe;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAgB;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAc,EAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,6FAA6F;QAC7F,wFAAwF;QACxF,2DAA2D;QAC3D,YAAY,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,QAAQ,CAAC,OAA8C;QACrD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/B,CAAC;IAED,WAAW,CAAC,QAA4C;QACtD,wEAAwE;IAC1E,CAAC;IAED,4FAA4F;IAC5F,8FAA8F;IAC9F,KAAK,CAAC,cAAc,CAAC,GAAmB;QACtC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,OAAsC;QAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACF;AApCD,8CAoCC"}
1
+ {"version":3,"file":"in-memory-transport.js","sourceRoot":"","sources":["../../src/testing/in-memory-transport.ts"],"names":[],"mappings":";;;AAQA,0CAA+D;AAE/D;;;;;GAKG;AACH,MAAa,iBAAiB;IACX,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IACnD,aAAa,CAAyC;IAC7C,eAAe,GAAG,IAAI,GAAG,EAAiC,CAAC;IAE5E,sDAAsD;IACtD,MAAM,CAAC,IAAY,EAAE,EAAe;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAgB;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,IAAA,yBAAc,EAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACxE,6FAA6F;QAC7F,wFAAwF;QACxF,2DAA2D;QAC3D,YAAY,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,QAAQ,CAAC,OAA8C;QACrD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/B,CAAC;IAED,WAAW,CAAC,QAA4C;QACtD,wEAAwE;IAC1E,CAAC;IAED,4FAA4F;IAC5F,8FAA8F;IAC9F,KAAK,CAAC,cAAc,CAAC,GAAmB;QACtC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,OAAsC;QAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;CACF;AApCD,8CAoCC"}
@@ -0,0 +1,23 @@
1
+ import type { Heartbeat, NamedTransport, RemoteTask, StepResult } from './interfaces';
2
+ /**
3
+ * An ordered pool of named transports. The engine dispatches on the first and fails over to the
4
+ * next on a dispatch error; a step can pin one by id. Pure transport plumbing — no run lifecycle —
5
+ * so it lives apart from the engine.
6
+ */
7
+ export declare class TransportPool {
8
+ private readonly transports;
9
+ constructor(transports: NamedTransport[]);
10
+ get size(): number;
11
+ /** Register the engine's result/heartbeat handlers on EVERY transport — a result can come back on
12
+ * whichever one delivered the task, so failover stays symmetric. */
13
+ bind(onResult: (result: StepResult) => Promise<void>, onHeartbeat: (beat: Heartbeat) => Promise<void>): void;
14
+ /**
15
+ * Dispatch `task` over the pool: try the preferred (or first) transport, fail over to the next on
16
+ * a dispatch error, and stamp the task with the id of the transport that accepted it (so a worker
17
+ * replies on the matching one). Throws if every transport fails.
18
+ */
19
+ dispatch(task: Omit<RemoteTask, 'transport'>, preferId?: string): Promise<void>;
20
+ /** Pinned `preferId` first, then the rest (failover order). */
21
+ private ordered;
22
+ }
23
+ //# sourceMappingURL=transport-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-pool.d.ts","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtF;;;;GAIG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,cAAc,EAAE;IAEzD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;yEACqE;IACrE,IAAI,CACF,QAAQ,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,EAC/C,WAAW,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,GAC9C,IAAI;IAOP;;;;OAIG;IACG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAarF,+DAA+D;IAC/D,OAAO,CAAC,OAAO;CAMhB"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransportPool = void 0;
4
+ /**
5
+ * An ordered pool of named transports. The engine dispatches on the first and fails over to the
6
+ * next on a dispatch error; a step can pin one by id. Pure transport plumbing — no run lifecycle —
7
+ * so it lives apart from the engine.
8
+ */
9
+ class TransportPool {
10
+ transports;
11
+ constructor(transports) {
12
+ this.transports = transports;
13
+ }
14
+ get size() {
15
+ return this.transports.length;
16
+ }
17
+ /** Register the engine's result/heartbeat handlers on EVERY transport — a result can come back on
18
+ * whichever one delivered the task, so failover stays symmetric. */
19
+ bind(onResult, onHeartbeat) {
20
+ for (const { transport } of this.transports) {
21
+ transport.onResult(onResult);
22
+ transport.onHeartbeat(onHeartbeat);
23
+ }
24
+ }
25
+ /**
26
+ * Dispatch `task` over the pool: try the preferred (or first) transport, fail over to the next on
27
+ * a dispatch error, and stamp the task with the id of the transport that accepted it (so a worker
28
+ * replies on the matching one). Throws if every transport fails.
29
+ */
30
+ async dispatch(task, preferId) {
31
+ let lastErr;
32
+ for (const { id, transport } of this.ordered(preferId)) {
33
+ try {
34
+ await transport.dispatch({ ...task, transport: id });
35
+ return;
36
+ }
37
+ catch (err) {
38
+ lastErr = err;
39
+ }
40
+ }
41
+ throw lastErr ?? new Error('no transport accepted the dispatch');
42
+ }
43
+ /** Pinned `preferId` first, then the rest (failover order). */
44
+ ordered(preferId) {
45
+ if (!preferId)
46
+ return this.transports;
47
+ const pref = this.transports.filter((t) => t.id === preferId);
48
+ if (pref.length === 0)
49
+ throw new Error(`transport "${preferId}" is not registered`);
50
+ return [...pref, ...this.transports.filter((t) => t.id !== preferId)];
51
+ }
52
+ }
53
+ exports.TransportPool = TransportPool;
54
+ //# sourceMappingURL=transport-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-pool.js","sourceRoot":"","sources":["../src/transport-pool.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACH,MAAa,aAAa;IACK;IAA7B,YAA6B,UAA4B;QAA5B,eAAU,GAAV,UAAU,CAAkB;IAAG,CAAC;IAE7D,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAChC,CAAC;IAED;yEACqE;IACrE,IAAI,CACF,QAA+C,EAC/C,WAA+C;QAE/C,KAAK,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC5C,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC7B,SAAS,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CAAC,IAAmC,EAAE,QAAiB;QACnE,IAAI,OAAgB,CAAC;QACrB,KAAK,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC;gBACH,MAAM,SAAS,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,GAAG,GAAG,CAAC;YAChB,CAAC;QACH,CAAC;QACD,MAAM,OAAO,IAAI,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACnE,CAAC;IAED,+DAA+D;IACvD,OAAO,CAAC,QAAiB;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC9D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,cAAc,QAAQ,qBAAqB,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC;IACxE,CAAC;CACF;AA5CD,sCA4CC"}
@@ -0,0 +1,46 @@
1
+ import type { RemoteStepDef, StateStore, StepError, StepEvent, StepKind, WorkflowCtx } from './interfaces';
2
+ /** A saga undo registered by a completed step, kept with its step name for visibility on failure. */
3
+ export interface Compensation {
4
+ name: string;
5
+ fn: () => Promise<void>;
6
+ }
7
+ /** A finished local step the host should checkpoint and announce (completed or failed). */
8
+ export interface StepRecord {
9
+ runId: string;
10
+ seq: number;
11
+ name: string;
12
+ kind: StepKind;
13
+ input?: unknown;
14
+ events?: StepEvent[];
15
+ attempts: number;
16
+ enqueuedAt: Date;
17
+ startedAt: Date;
18
+ workerGroup?: string;
19
+ }
20
+ /**
21
+ * The narrow surface {@link createWorkflowCtx} needs from the engine — the seam between the
22
+ * authoring API (this module) and the orchestrator (the engine owns lifecycle: emitting events,
23
+ * suspending/resuming runs, dispatching remote steps).
24
+ */
25
+ export interface CtxHost {
26
+ readonly store: StateStore;
27
+ clock(): number;
28
+ webhookUrl?: (token: string) => string;
29
+ completeStep(step: StepRecord & {
30
+ output: unknown;
31
+ }): Promise<void>;
32
+ failStep(step: StepRecord & {
33
+ error: StepError;
34
+ }): Promise<void>;
35
+ callRemote<TInput, TOutput>(runId: string, seq: number, step: RemoteStepDef<TInput, TOutput>, input: TInput, queue?: string, transport?: string): Promise<TOutput>;
36
+ /** Start a child run once, deferred so it can't reentrantly resume a still-running parent. */
37
+ startChild(workflow: string, input: unknown, id: string): void;
38
+ }
39
+ /**
40
+ * Build the {@link WorkflowCtx} handed to a workflow body. Every primitive is a closure over the
41
+ * position counter (the per-run logical position) and the saga `compensations` stack, so `task`/
42
+ * `child` compose `step`/`waitForSignal` directly. All durability goes through {@link CtxHost}, so
43
+ * the workflow body stays deterministic.
44
+ */
45
+ export declare function createWorkflowCtx(host: CtxHost, runId: string, compensations: Compensation[]): WorkflowCtx;
46
+ //# sourceMappingURL=workflow-ctx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-ctx.d.ts","sourceRoot":"","sources":["../src/workflow-ctx.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,aAAa,EACb,UAAU,EACV,SAAS,EACT,SAAS,EACT,QAAQ,EAGR,WAAW,EACZ,MAAM,cAAc,CAAC;AAItB,qGAAqG;AACrG,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,2FAA2F;AAC3F,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,KAAK,IAAI,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG;QAAE,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,CAAC,MAAM,EAAE,OAAO,EACxB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,8FAA8F;IAC9F,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAChE;AAcD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,YAAY,EAAE,GAC5B,WAAW,CA2Pb"}
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWorkflowCtx = createWorkflowCtx;
4
+ const backoff_1 = require("./backoff");
5
+ const checkpoints_1 = require("./checkpoints");
6
+ const completion_1 = require("./completion");
7
+ const duration_1 = require("./duration");
8
+ const errors_1 = require("./errors");
9
+ const protocol_1 = require("./protocol");
10
+ const step_logger_1 = require("./step-logger");
11
+ /** The per-run logical position counter. `rewind()` gives a position back (see `ctx.patched`). */
12
+ class Position {
13
+ seq = -1;
14
+ next() {
15
+ this.seq += 1;
16
+ return this.seq;
17
+ }
18
+ rewind() {
19
+ this.seq -= 1;
20
+ }
21
+ }
22
+ /**
23
+ * Build the {@link WorkflowCtx} handed to a workflow body. Every primitive is a closure over the
24
+ * position counter (the per-run logical position) and the saga `compensations` stack, so `task`/
25
+ * `child` compose `step`/`waitForSignal` directly. All durability goes through {@link CtxHost}, so
26
+ * the workflow body stays deterministic.
27
+ */
28
+ function createWorkflowCtx(host, runId, compensations) {
29
+ const { store } = host;
30
+ const pos = new Position();
31
+ const step = async (name, fn, options) => {
32
+ const current = pos.next();
33
+ const existing = await store.getCheckpoint(runId, current);
34
+ if (existing && existing.name !== name) {
35
+ throw new errors_1.NonDeterminismError(runId, current, name, existing.name);
36
+ }
37
+ if (existing && existing.status === 'completed') {
38
+ // Register the compensation on replay too, so a saga undoes ALL completed steps — even
39
+ // those done in an earlier (since-suspended) pass — not just the ones run this pass.
40
+ if (options?.compensate)
41
+ compensations.push({ name, fn: options.compensate });
42
+ return existing.output;
43
+ }
44
+ const maxAttempts = Math.max(1, options?.retries ?? 1);
45
+ const startedAt = new Date();
46
+ for (let attempt = 1;; attempt += 1) {
47
+ // Events are scoped per attempt — a retry starts a clean log, so the checkpoint reflects
48
+ // only the attempt that actually completed (or the final failing one).
49
+ const events = [];
50
+ try {
51
+ const output = await fn((0, step_logger_1.createStepLogger)(events, host.clock));
52
+ await host.completeStep({
53
+ runId,
54
+ seq: current,
55
+ name,
56
+ kind: 'local',
57
+ output,
58
+ events,
59
+ attempts: attempt,
60
+ enqueuedAt: startedAt,
61
+ startedAt,
62
+ });
63
+ if (options?.compensate)
64
+ compensations.push({ name, fn: options.compensate });
65
+ return output;
66
+ }
67
+ catch (err) {
68
+ if (err instanceof errors_1.FatalError || attempt >= maxAttempts) {
69
+ await host.failStep({
70
+ runId,
71
+ seq: current,
72
+ name,
73
+ kind: 'local',
74
+ error: {
75
+ message: err instanceof Error ? err.message : String(err),
76
+ stack: err instanceof Error ? err.stack : undefined,
77
+ },
78
+ events,
79
+ attempts: attempt,
80
+ enqueuedAt: startedAt,
81
+ startedAt,
82
+ });
83
+ throw err;
84
+ }
85
+ // Wait out the backoff before the next attempt (no-op when backoffMs is unset).
86
+ const wait = (0, backoff_1.backoffDelay)(attempt, options);
87
+ if (wait > 0)
88
+ await new Promise((resolve) => setTimeout(resolve, wait));
89
+ }
90
+ }
91
+ };
92
+ const sleep = async (duration) => {
93
+ const current = pos.next();
94
+ const now = host.clock();
95
+ const existing = await store.getCheckpoint(runId, current);
96
+ if (existing) {
97
+ // Timer already recorded: resume if due, otherwise re-suspend cheaply.
98
+ if (now >= (existing.wakeAt ?? 0))
99
+ return;
100
+ throw new errors_1.WorkflowSuspended(existing.wakeAt ?? now);
101
+ }
102
+ const wakeAt = now + (0, duration_1.parseDuration)(duration);
103
+ await store.saveCheckpoint((0, checkpoints_1.instantCheckpoint)({ runId, seq: current, name: 'sleep', kind: 'sleep', wakeAt }));
104
+ throw new errors_1.WorkflowSuspended(wakeAt);
105
+ };
106
+ // NOTE (determinism): a bounded wait consumes TWO logical positions (deadline + wait), an
107
+ // unbounded one consumes ONE. So adding or removing `{ timeoutMs }` on an existing `waitForSignal`
108
+ // shifts the seq of every later step — treat it as a workflow-version change for in-flight runs.
109
+ const waitForSignal = async (token, opts) => {
110
+ if (opts?.timeoutMs == null) {
111
+ const current = pos.next();
112
+ const existing = await store.getCheckpoint(runId, current);
113
+ if (existing && existing.status === 'completed')
114
+ return existing.output;
115
+ await store.putSignalWaiter({ token, runId, seq: current });
116
+ throw new errors_1.WorkflowSuspended();
117
+ }
118
+ const timeoutMs = opts.timeoutMs;
119
+ const deadlineSeq = pos.next();
120
+ const waitSeq = pos.next();
121
+ // The deadline is recorded durably as a timer checkpoint so replay knows it; the run also gets a
122
+ // run-level wakeAt (via WorkflowSuspended) so the timer poller resumes it at the deadline.
123
+ const recorded = await store.getCheckpoint(runId, deadlineSeq);
124
+ const deadline = recorded?.wakeAt ?? host.clock() + timeoutMs;
125
+ if (!recorded) {
126
+ await store.saveCheckpoint((0, checkpoints_1.instantCheckpoint)({
127
+ runId,
128
+ seq: deadlineSeq,
129
+ name: `timeout:${token}`,
130
+ kind: 'sleep',
131
+ wakeAt: deadline,
132
+ }));
133
+ }
134
+ const waited = await store.getCheckpoint(runId, waitSeq);
135
+ if (waited && waited.status === 'completed')
136
+ return waited.output;
137
+ if (host.clock() >= deadline) {
138
+ await store.takeSignalWaiter(token).catch(() => undefined);
139
+ throw new errors_1.SignalTimeoutError(token, timeoutMs);
140
+ }
141
+ await store.putSignalWaiter({ token, runId, seq: waitSeq });
142
+ throw new errors_1.WorkflowSuspended(deadline);
143
+ };
144
+ // An external task = a checkpointed dispatch + a wait for its async-completion `Completion`
145
+ // (delivered by engine.completeTask/failTask). The whole "fire at a foreign system, suspend,
146
+ // resume when it reports back" pattern as one call.
147
+ const task = async (name, dispatch, options) => {
148
+ await step(`task:dispatch:${name}`, dispatch, options);
149
+ return (0, completion_1.unwrapCompletion)(await waitForSignal(`task:${runId}:${name}`), `task "${name}"`);
150
+ };
151
+ // Child workflow: start it once, then suspend on a `child:<id>` waiter the child signals on its
152
+ // terminal state (see engine.notifyParent).
153
+ const child = async (workflow, input, childId) => {
154
+ const current = pos.next();
155
+ const id = childId ?? `${runId}.child.${current}`;
156
+ const existing = await store.getCheckpoint(runId, current);
157
+ if (existing && existing.status === 'completed') {
158
+ return (0, completion_1.unwrapCompletion)(existing.output, `child "${id}"`);
159
+ }
160
+ await store.putSignalWaiter({ token: `child:${id}`, runId, seq: current });
161
+ if (!(await store.getRun(id)))
162
+ host.startChild(workflow, input, id);
163
+ throw new errors_1.WorkflowSuspended();
164
+ };
165
+ // A breakpoint = a visible `pending` checkpoint + a signal waiter the dashboard resumes via
166
+ // `engine.continue`. Reuses the signal machinery, so resume overwrites the pending checkpoint
167
+ // with a completed one and the run replays past it.
168
+ const breakpoint = async (label) => {
169
+ const current = pos.next();
170
+ const existing = await store.getCheckpoint(runId, current);
171
+ if (existing && existing.status === 'completed')
172
+ return;
173
+ if (!existing) {
174
+ await store.saveCheckpoint((0, checkpoints_1.instantCheckpoint)({
175
+ runId,
176
+ seq: current,
177
+ name: label ? `breakpoint:${label}` : 'breakpoint',
178
+ kind: 'signal',
179
+ status: 'pending',
180
+ }));
181
+ await store.putSignalWaiter({ token: (0, protocol_1.breakpointToken)(runId, current), runId, seq: current });
182
+ }
183
+ throw new errors_1.WorkflowSuspended();
184
+ };
185
+ // Guard an in-place change: a fresh run records a `patch:<id>` marker here and takes the new
186
+ // branch; a run recorded under the OLD code finds a real step at this position instead, so we
187
+ // rewind the logical position (the marker is transparent to it) and return false — its replay
188
+ // reads that old step next and follows the old branch. No position shift → no corruption.
189
+ const patched = async (id) => {
190
+ const marker = `patch:${id}`;
191
+ const current = pos.next();
192
+ const existing = await store.getCheckpoint(runId, current);
193
+ if (existing) {
194
+ if (existing.name === marker)
195
+ return true;
196
+ if (existing.name.startsWith('patch:')) {
197
+ throw new errors_1.NonDeterminismError(runId, current, marker, existing.name);
198
+ }
199
+ pos.rewind(); // not a marker: an old run's step lives here — give the position back to it
200
+ return false;
201
+ }
202
+ await store.saveCheckpoint((0, checkpoints_1.instantCheckpoint)({ runId, seq: current, name: marker, kind: 'local', output: true }));
203
+ return true;
204
+ };
205
+ // An update point: suspend on a run-scoped `update:<runId>:<name>` token that engine.update
206
+ // delivers to (after its validator passes). Reuses the signal machinery; run-scoped like task/child.
207
+ const onUpdate = (name, opts) => waitForSignal(`update:${runId}:${name}`, opts);
208
+ // A queryable named value: a checkpoint whose `name` is `event:<key>`, so the latest value for a
209
+ // key is just the highest-seq such checkpoint (read by engine.getEvent). Replay-idempotent.
210
+ const setEvent = async (key, value) => {
211
+ const current = pos.next();
212
+ const name = `event:${key}`;
213
+ const existing = await store.getCheckpoint(runId, current);
214
+ if (existing && existing.name !== name) {
215
+ throw new errors_1.NonDeterminismError(runId, current, name, existing.name);
216
+ }
217
+ if (existing && existing.status === 'completed')
218
+ return; // replay: already published
219
+ await store.saveCheckpoint((0, checkpoints_1.instantCheckpoint)({ runId, seq: current, name, kind: 'local', output: value }));
220
+ };
221
+ // A durable webhook reserves a logical position NOW to mint a stable token, so the url can be
222
+ // handed to a third party before `wait()` suspends. `wait()` then parks on that same position
223
+ // until the callback lands as engine.signal(token, body) — single position, replay-safe.
224
+ const webhook = () => {
225
+ const current = pos.next();
226
+ const token = `wh:${runId}:${current}`;
227
+ const wait = async () => {
228
+ const existing = await store.getCheckpoint(runId, current);
229
+ if (existing && existing.status === 'completed')
230
+ return existing.output;
231
+ await store.putSignalWaiter({ token, runId, seq: current });
232
+ throw new errors_1.WorkflowSuspended();
233
+ };
234
+ return { token, url: host.webhookUrl?.(token), wait };
235
+ };
236
+ // Deterministic non-deterministic sources: each is a checkpointed local step, so the value is
237
+ // captured on the first run and replayed verbatim (a raw Date.now()/Math.random() inside a
238
+ // workflow would differ across replays and corrupt the run).
239
+ const now = () => step('now', async () => host.clock());
240
+ const random = () => step('random', async () => Math.random());
241
+ const uuid = () => step('uuid', async () => globalThis.crypto.randomUUID());
242
+ return {
243
+ runId,
244
+ step,
245
+ sleep,
246
+ waitForSignal,
247
+ task,
248
+ child,
249
+ breakpoint,
250
+ webhook,
251
+ setEvent,
252
+ onUpdate,
253
+ patched,
254
+ now,
255
+ random,
256
+ uuid,
257
+ call: (remote, input, opts) => host.callRemote(runId, pos.next(), remote, input, opts?.queue, opts?.transport),
258
+ };
259
+ }
260
+ //# sourceMappingURL=workflow-ctx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-ctx.js","sourceRoot":"","sources":["../src/workflow-ctx.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dudousxd/nestjs-durable-core",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Durable workflows for NestJS — core interfaces, engine and deterministic replay",
5
5
  "license": "MIT",
6
6
  "author": "Davide Carvalho",
@@ -16,10 +16,17 @@
16
16
  "dist"
17
17
  ],
18
18
  "peerDependencies": {
19
+ "cron-parser": "^4.0.0 || ^5.0.0",
19
20
  "reflect-metadata": "^0.2.0",
20
21
  "zod": "^3.0.0 || ^4.0.0"
21
22
  },
23
+ "peerDependenciesMeta": {
24
+ "cron-parser": {
25
+ "optional": true
26
+ }
27
+ },
22
28
  "devDependencies": {
29
+ "cron-parser": "4.9.0",
23
30
  "reflect-metadata": "0.2.2",
24
31
  "typescript": "5.9.3",
25
32
  "zod": "3.25.76"