@yieldstar/core 0.5.0 → 0.6.1

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 (64) hide show
  1. package/dist/base/durable-value.d.ts +71 -0
  2. package/dist/base/durable-value.d.ts.map +1 -0
  3. package/dist/base/durable-value.test.d.ts +2 -0
  4. package/dist/base/durable-value.test.d.ts.map +1 -0
  5. package/dist/base/effect.d.ts +136 -0
  6. package/dist/base/effect.d.ts.map +1 -0
  7. package/dist/base/errors.d.ts +23 -0
  8. package/dist/base/errors.d.ts.map +1 -0
  9. package/dist/base/errors.test.d.ts +2 -0
  10. package/dist/base/errors.test.d.ts.map +1 -0
  11. package/dist/base/event.d.ts +6 -1
  12. package/dist/base/event.d.ts.map +1 -1
  13. package/dist/base/execution.d.ts +255 -0
  14. package/dist/base/execution.d.ts.map +1 -0
  15. package/dist/base/heap.d.ts +15 -3
  16. package/dist/base/heap.d.ts.map +1 -1
  17. package/dist/base/invoker.d.ts +47 -2
  18. package/dist/base/invoker.d.ts.map +1 -1
  19. package/dist/base/runtime.d.ts +27 -4
  20. package/dist/base/runtime.d.ts.map +1 -1
  21. package/dist/base/step.d.ts +21 -5
  22. package/dist/base/step.d.ts.map +1 -1
  23. package/dist/base/store.d.ts +135 -21
  24. package/dist/base/store.d.ts.map +1 -1
  25. package/dist/base/workflow.d.ts +15 -0
  26. package/dist/base/workflow.d.ts.map +1 -1
  27. package/dist/index.d.ts +23 -6
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1653 -172
  30. package/dist/lib/effect-state.d.ts +78 -0
  31. package/dist/lib/effect-state.d.ts.map +1 -0
  32. package/dist/lib/execution-dispatcher.d.ts +112 -0
  33. package/dist/lib/execution-dispatcher.d.ts.map +1 -0
  34. package/dist/lib/execution-state.d.ts +248 -0
  35. package/dist/lib/execution-state.d.ts.map +1 -0
  36. package/dist/lib/execution-state.test.d.ts +2 -0
  37. package/dist/lib/execution-state.test.d.ts.map +1 -0
  38. package/dist/lib/wait-for-outcome.d.ts +15 -0
  39. package/dist/lib/wait-for-outcome.d.ts.map +1 -0
  40. package/dist/lib/workflow-runner.d.ts +14 -9
  41. package/dist/lib/workflow-runner.d.ts.map +1 -1
  42. package/package.json +1 -1
  43. package/src/base/durable-value.test.ts +285 -0
  44. package/src/base/durable-value.ts +442 -0
  45. package/src/base/effect.ts +165 -0
  46. package/src/base/errors.test.ts +210 -0
  47. package/src/base/errors.ts +72 -0
  48. package/src/base/event.ts +6 -1
  49. package/src/base/execution.ts +315 -0
  50. package/src/base/heap.ts +17 -3
  51. package/src/base/invoker.ts +60 -2
  52. package/src/base/runtime.ts +28 -7
  53. package/src/base/step.ts +29 -7
  54. package/src/base/store.ts +339 -49
  55. package/src/base/workflow.ts +15 -0
  56. package/src/index.ts +138 -3
  57. package/src/lib/effect-state.ts +254 -0
  58. package/src/lib/execution-dispatcher.ts +408 -0
  59. package/src/lib/execution-state.test.ts +249 -0
  60. package/src/lib/execution-state.ts +650 -0
  61. package/src/lib/wait-for-outcome.ts +40 -0
  62. package/src/lib/workflow-runner.ts +75 -43
  63. package/src/base/scheduler.ts +0 -8
  64. package/tsconfig.tsbuildinfo +0 -1
@@ -1,7 +1,65 @@
1
1
  import type { EventEmitter } from "node:events";
2
- import type { ExecutionEvent } from "./event";
2
+ import type { WorkflowEvent } from "./event";
3
+ import type { ExecutionLease, WorkflowRunOutcome } from "./execution";
4
+
5
+ export type DeliveryOptions = {
6
+ /** Every fenced write the delivery makes carries this lease. */
7
+ lease: ExecutionLease;
8
+ /**
9
+ * Aborted when the delivery must stop: the dispatcher aborts it, with a
10
+ * `LeaseLostError` as its reason, when a renewal returns `lost`. The driver
11
+ * checks it before each step function and each fenced write, and ends an
12
+ * aborted delivery without running more workflow code.
13
+ */
14
+ signal: AbortSignal;
15
+ };
3
16
 
4
17
  export type WorkflowInvoker = {
18
+ /**
19
+ * @deprecated The execution record is the source of truth for outcomes.
20
+ * The dispatcher still emits terminal outcomes here as an in-process fast
21
+ * path; no guarantee depends on it.
22
+ */
5
23
  workflowEndEmitter: EventEmitter;
6
- execute(event: ExecutionEvent): Promise<void>;
24
+ /**
25
+ * Runs one delivery of an execution and resolves with its outcome. Rejects,
26
+ * without an outcome, when the delivery hits an infrastructure error or the
27
+ * worker exits before replying. Once `options.signal` aborts, the delivery runs
28
+ * no more workflow code and makes no more fenced writes; it rejects with an
29
+ * `InfrastructureError` whose cause is the signal's reason. An invoker that
30
+ * can stop a step function already running, as the worker invoker does by
31
+ * killing its worker, should do so and reject at once. The dispatcher
32
+ * abandons a delivery that has not settled within its `abortGracePeriod`
33
+ * of the abort, and frees its slot.
34
+ *
35
+ * A worker that exits before replying rejects with a `WorkerExitedError`:
36
+ * the dispatcher then leaves the lease to expire, because the worker's last
37
+ * writes may still be landing. Every other rejection is a retry reply, and
38
+ * the dispatcher releases the lease.
39
+ */
40
+ deliver(event: WorkflowEvent, options: DeliveryOptions): Promise<WorkflowRunOutcome>;
7
41
  };
42
+
43
+ const WORKER_EXITED = Symbol.for("yieldstar.workerExited");
44
+
45
+ /**
46
+ * Rejects a delivery whose worker exited, or was killed, before replying.
47
+ * The dispatcher does not release the lease: it expires, and the execution is
48
+ * delivered again after the redelivery delay.
49
+ */
50
+ export class WorkerExitedError extends Error {
51
+ readonly [WORKER_EXITED] = true;
52
+
53
+ constructor(message: string) {
54
+ super(message);
55
+ this.name = "WorkerExitedError";
56
+ }
57
+
58
+ static is(value: unknown): value is WorkerExitedError {
59
+ return (
60
+ typeof value === "object" &&
61
+ value !== null &&
62
+ (value as Record<symbol, unknown>)[WORKER_EXITED] === true
63
+ );
64
+ }
65
+ }
@@ -1,8 +1,29 @@
1
- import type { Logger } from "pino";
2
- import type { WorkflowResult } from "./step";
3
- import type { WorkflowEvent } from "./event";
1
+ import type { EffectClient } from "./effect";
2
+ import type { ExecutionClient } from "./execution";
3
+ import type { HeapClient } from "./heap";
4
+ import type { StoreClient } from "./store";
4
5
 
5
- export type EventProcessor = (
6
- event: WorkflowEvent,
7
- logger: Logger
8
- ) => Promise<void | WorkflowResult<any>>;
6
+ export interface RuntimeOptions {
7
+ /** Every client of the runtime reads time from this clock. Defaults to `Date.now`. */
8
+ clock?: () => number;
9
+ }
10
+
11
+ /**
12
+ * A runtime is defined by the guarantees its clients keep, not by how many
13
+ * databases it uses:
14
+ *
15
+ * - Where one write must accompany another, such as the wakes for a store
16
+ * commit, the second is durable once the first commits and is applied
17
+ * eventually (in one transaction or through an outbox).
18
+ * - A store or effect waiter is deleted atomically with its step's result.
19
+ * - An effect's settlement and the wakes of its waiters are one atomic write.
20
+ * - Every client reads time from the runtime's clock.
21
+ */
22
+ export abstract class Runtime {
23
+ /** The clock every client, and every step's wake time, reads. */
24
+ abstract readonly clock: () => number;
25
+ abstract readonly executions: ExecutionClient;
26
+ abstract readonly effects: EffectClient;
27
+ abstract readonly heap: HeapClient;
28
+ abstract readonly stores: StoreClient;
29
+ }
package/src/base/step.ts CHANGED
@@ -22,13 +22,18 @@ export class StepInvalid extends StepResponse {
22
22
  readonly type = "step-invalid";
23
23
  }
24
24
 
25
+ export type StepSchemaVerdict = "accepted" | "rejected";
26
+
25
27
  export class StepResult extends StepResponse {
26
28
  static type = "step-result";
27
29
  readonly type = "step-result";
28
30
  result: any;
29
- constructor(result: any) {
31
+ /** Whether the step's schema accepted its value on the first run. */
32
+ schema?: StepSchemaVerdict;
33
+ constructor(result: any, schema?: StepSchemaVerdict) {
30
34
  super();
31
35
  this.result = result;
36
+ if (schema !== undefined) this.schema = schema;
32
37
  }
33
38
  }
34
39
 
@@ -45,10 +50,11 @@ export class WorkflowResult<T extends any> extends StepResponse {
45
50
  export class WorkflowDelay extends StepResponse {
46
51
  static type = "workflow-delay";
47
52
  readonly type = "workflow-delay";
48
- resumeIn: number;
49
- constructor(resumeIn: number) {
53
+ /** The absolute time the step's pause ends, read from the runtime clock. */
54
+ wakeAt: number;
55
+ constructor(wakeAt: number) {
50
56
  super();
51
- this.resumeIn = resumeIn;
57
+ this.wakeAt = wakeAt;
52
58
  }
53
59
  }
54
60
 
@@ -60,6 +66,21 @@ export class StepStoreWait extends StepResponse {
60
66
  }
61
67
  }
62
68
 
69
+ /**
70
+ * An effect step whose outcome is uncertain. The driver records it as an
71
+ * unfinished step after watching the effect, so the next delivery begins the
72
+ * effect again; `wakeAt` is when that delivery is due.
73
+ */
74
+ export class StepEffectWait extends StepResponse {
75
+ static type = "effect-wait";
76
+ readonly type = "effect-wait";
77
+ wakeAt: number;
78
+ constructor(wakeAt: number) {
79
+ super();
80
+ this.wakeAt = wakeAt;
81
+ }
82
+ }
83
+
63
84
  export class WorkflowRestart extends StepResponse {
64
85
  static type = "workflow-restart";
65
86
  readonly type = "workflow-restart";
@@ -96,9 +117,10 @@ export class StepError extends StepResponse {
96
117
  export class StepDelay extends StepResponse {
97
118
  static type = "step-delay";
98
119
  readonly type = "step-delay";
99
- resumeIn: number;
100
- constructor(resumeIn: number) {
120
+ /** The absolute time the step's pause ends, read from the runtime clock. */
121
+ wakeAt: number;
122
+ constructor(wakeAt: number) {
101
123
  super();
102
- this.resumeIn = resumeIn;
124
+ this.wakeAt = wakeAt;
103
125
  }
104
126
  }