@asaidimu/utils-pipeline 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -276
- package/index.d.mts +126 -39
- package/index.d.ts +126 -39
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1182,22 +1182,27 @@ interface State {
|
|
|
1182
1182
|
[key: string]: any;
|
|
1183
1183
|
}
|
|
1184
1184
|
/**
|
|
1185
|
-
* Instructs the
|
|
1186
|
-
*
|
|
1185
|
+
* Instructs the factory to pause the pipeline.
|
|
1186
|
+
*
|
|
1187
|
+
* - `pause` — the `stageId` at which the pipeline should resume.
|
|
1188
|
+
* - `timeout` — how long (ms) the registry should hold the live RunContext
|
|
1189
|
+
* before running the deferred container export and clearing the
|
|
1190
|
+
* strong reference. Omit to use the registry's configured default.
|
|
1191
|
+
* A value of 0 means export immediately on pause (no deferral).
|
|
1192
|
+
* - `persist` — kept for backward compatibility; when true the registry will
|
|
1193
|
+
* always export the container bundle at expiry regardless of
|
|
1194
|
+
* whether resume was called. Ignored if timeout is 0.
|
|
1187
1195
|
*/
|
|
1188
1196
|
interface PauseInstruction {
|
|
1189
1197
|
readonly pause: string;
|
|
1190
|
-
|
|
1191
|
-
* If true, the engine will snapshot the entire ArtifactContainer
|
|
1192
|
-
* and store the bundle in the checkpoint. Defaults to false.
|
|
1193
|
-
*/
|
|
1198
|
+
readonly timeout?: number;
|
|
1194
1199
|
readonly persist?: boolean;
|
|
1195
1200
|
}
|
|
1196
1201
|
/**
|
|
1197
1202
|
* All possible outcomes of a router:
|
|
1198
|
-
* - `string`
|
|
1199
|
-
* - `null`
|
|
1200
|
-
* - `undefined`
|
|
1203
|
+
* - `string` → jump to a named stage
|
|
1204
|
+
* - `null` → terminate the pipeline
|
|
1205
|
+
* - `undefined` → advance to the next stage in order (or natural end)
|
|
1201
1206
|
* - `PauseInstruction` → suspend and write a checkpoint
|
|
1202
1207
|
*/
|
|
1203
1208
|
type RoutingInstruction = string | null | undefined | PauseInstruction;
|
|
@@ -1220,6 +1225,10 @@ type PipelineStageRouter<S extends object> = (state: S, results: Record<string,
|
|
|
1220
1225
|
*
|
|
1221
1226
|
* The checkpoint is always written atomically with the state patches of the
|
|
1222
1227
|
* stage that triggered the pause.
|
|
1228
|
+
*
|
|
1229
|
+
* `containerBundle` is intentionally absent at write time — the factory never
|
|
1230
|
+
* exports. The registry writes it into the checkpoint (via writeCheckpoint)
|
|
1231
|
+
* when the pause timeout fires and the live RunContext is about to be released.
|
|
1223
1232
|
*/
|
|
1224
1233
|
interface PipelineCheckpoint {
|
|
1225
1234
|
readonly runId: string;
|
|
@@ -1228,9 +1237,10 @@ interface PipelineCheckpoint {
|
|
|
1228
1237
|
readonly pausedAtStageId: string;
|
|
1229
1238
|
readonly pausedAtStageLabel: string;
|
|
1230
1239
|
readonly pausedOn: string;
|
|
1240
|
+
/** Written by the registry at timeout expiry, never by the factory. */
|
|
1231
1241
|
readonly containerBundle?: ExportedContainerState;
|
|
1232
1242
|
}
|
|
1233
|
-
/**
|
|
1243
|
+
/** Factory-internal namespace for all checkpoint data. */
|
|
1234
1244
|
declare const PIPELINE_DATA_KEY: "__pipeline_data__";
|
|
1235
1245
|
/**
|
|
1236
1246
|
* Run-scoped context injected into every step action as a second argument.
|
|
@@ -1391,10 +1401,14 @@ type EventPath = readonly PathNode[];
|
|
|
1391
1401
|
/**
|
|
1392
1402
|
* All events emitted during a run.
|
|
1393
1403
|
*
|
|
1394
|
-
* stage:paused (#
|
|
1404
|
+
* stage:paused (#8) is a dedicated event for stages that pause, distinct from
|
|
1395
1405
|
* stage:success. Consumers should listen to both if they want to react to all
|
|
1396
1406
|
* terminal stage outcomes. stage:success is only emitted when the stage
|
|
1397
1407
|
* advances (or terminates) — never when it pauses.
|
|
1408
|
+
*
|
|
1409
|
+
* pipeline:paused carries `pauseTimeout` forwarded from the PauseInstruction
|
|
1410
|
+
* so the PipelineRegistry can arm its cleanup timer with the correct duration
|
|
1411
|
+
* without re-reading or re-parsing the instruction.
|
|
1398
1412
|
*/
|
|
1399
1413
|
interface RunEventMap<S extends object> {
|
|
1400
1414
|
"pipeline:start": {
|
|
@@ -1417,6 +1431,12 @@ interface RunEventMap<S extends object> {
|
|
|
1417
1431
|
runId: string;
|
|
1418
1432
|
checkpoint: PipelineCheckpoint;
|
|
1419
1433
|
finalState: S;
|
|
1434
|
+
/**
|
|
1435
|
+
* The timeout value from the PauseInstruction, forwarded verbatim.
|
|
1436
|
+
* Undefined means the registry should use its configured default.
|
|
1437
|
+
* 0 means export immediately (no deferral window).
|
|
1438
|
+
*/
|
|
1439
|
+
pauseTimeout: number | undefined;
|
|
1420
1440
|
};
|
|
1421
1441
|
"pipeline:failure": {
|
|
1422
1442
|
path: EventPath;
|
|
@@ -1503,8 +1523,8 @@ interface ScopedEventBus<S extends object> {
|
|
|
1503
1523
|
on<K extends keyof RunEventMap<S>>(event: K, handler: RunEventHandler<S, K>): () => void;
|
|
1504
1524
|
}
|
|
1505
1525
|
/**
|
|
1506
|
-
* A unit of execution returned by {@link
|
|
1507
|
-
* {@link
|
|
1526
|
+
* A unit of execution returned by {@link PipelineFactory.prepare} or
|
|
1527
|
+
* {@link PipelineFactory.resume}.
|
|
1508
1528
|
*
|
|
1509
1529
|
* Subscribe to lifecycle events via {@link on}, abort via {@link abort}, and
|
|
1510
1530
|
* start execution with {@link run}.
|
|
@@ -1529,27 +1549,29 @@ interface RunContext<S extends object> {
|
|
|
1529
1549
|
*/
|
|
1530
1550
|
run(): Promise<Result<PipelineRunResult<S>>>;
|
|
1531
1551
|
}
|
|
1532
|
-
/** Minimal logger interface used by the
|
|
1552
|
+
/** Minimal logger interface used by the factory. */
|
|
1533
1553
|
interface EngineLogger {
|
|
1534
1554
|
info: (msg: string, ctx?: any) => void;
|
|
1535
1555
|
error: (msg: string, ctx?: any) => void;
|
|
1536
1556
|
}
|
|
1537
1557
|
/**
|
|
1538
|
-
* Configuration for {@link
|
|
1558
|
+
* Configuration for {@link PipelineFactory}.
|
|
1539
1559
|
*
|
|
1540
1560
|
* @typeParam S - The shape of the state managed by the pipeline.
|
|
1541
1561
|
*/
|
|
1542
|
-
interface
|
|
1562
|
+
interface PipelineFactoryOptions<S extends object = State> {
|
|
1543
1563
|
/** Logger (defaults to a no‑op). */
|
|
1544
1564
|
logger?: EngineLogger;
|
|
1545
1565
|
/**
|
|
1546
1566
|
* **Required.** A factory that, given a `runId`, returns a `DataStore<S>`.
|
|
1547
|
-
* The
|
|
1548
|
-
* isolated store instance.
|
|
1567
|
+
* The factory does **not** hold a global store; each run receives its own
|
|
1568
|
+
* isolated store instance from this function.
|
|
1549
1569
|
*
|
|
1550
|
-
* For a new run (`prepare`), the
|
|
1570
|
+
* For a new run (`prepare`), the function should return an empty store.
|
|
1551
1571
|
* For a resumed run (`resume`), it must return the **same** store that was
|
|
1552
1572
|
* used during the original run (so that state and checkpoints are preserved).
|
|
1573
|
+
*
|
|
1574
|
+
* The returned store is owned by the run, not by PipelineFactory.
|
|
1553
1575
|
*/
|
|
1554
1576
|
storeFactory: (runId: string) => Promise<DataStore<S>>;
|
|
1555
1577
|
/**
|
|
@@ -1558,37 +1580,65 @@ interface PipelineEngineOptions<S extends object = State> {
|
|
|
1558
1580
|
* If omitted, the store remains empty.
|
|
1559
1581
|
*/
|
|
1560
1582
|
initialStateFactory?: () => S;
|
|
1583
|
+
/**
|
|
1584
|
+
* Optional registry to register every RunContext with after construction.
|
|
1585
|
+
* When provided, prepare() and resume() call registry.register() before
|
|
1586
|
+
* returning, passing both the RunContext and the run's DataStore so the
|
|
1587
|
+
* registry can drive deferred export without needing a reference to the factory.
|
|
1588
|
+
*/
|
|
1589
|
+
registry?: PipelineRegistryBinding<S>;
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Narrow interface the factory uses to register runs with the registry.
|
|
1593
|
+
* Typed as an interface rather than the full PipelineRegistry class so that
|
|
1594
|
+
* the factory remains decoupled from the registry's full surface.
|
|
1595
|
+
*/
|
|
1596
|
+
interface PipelineRegistryBinding<S extends object> {
|
|
1597
|
+
register(context: RunContext<S>, store: DataStore<S>): void;
|
|
1598
|
+
/**
|
|
1599
|
+
* Called by resume() before constructing a new RunContext.
|
|
1600
|
+
* Returns the existing live RunContext if the registry still holds a strong
|
|
1601
|
+
* reference for this runId (i.e. the pause timeout has not yet fired).
|
|
1602
|
+
* Returns null if no live context exists and reconstruction is needed.
|
|
1603
|
+
*/
|
|
1604
|
+
getLiveContext(runId: string): RunContext<S> | null;
|
|
1561
1605
|
}
|
|
1562
1606
|
/**
|
|
1563
|
-
*
|
|
1607
|
+
* A pure factory for creating and resuming pipeline runs.
|
|
1608
|
+
*
|
|
1609
|
+
* PipelineFactory is stateless between runs. It holds only the pipeline
|
|
1610
|
+
* definition (topology), a storeFactory function, and an optional logger and
|
|
1611
|
+
* registry binding. It does not own any DataStore, timer, or live run state.
|
|
1564
1612
|
*
|
|
1565
1613
|
* @typeParam S - The shape of the state object.
|
|
1566
1614
|
*
|
|
1567
1615
|
* @example
|
|
1568
1616
|
* ```ts
|
|
1569
|
-
* const
|
|
1617
|
+
* const factory = new PipelineFactory(myDefinition, {
|
|
1570
1618
|
* storeFactory: (runId) => createMyStore(runId),
|
|
1571
1619
|
* initialStateFactory: () => ({ counter: 0 }),
|
|
1620
|
+
* registry: PipelineRegistry.default,
|
|
1572
1621
|
* });
|
|
1573
1622
|
*
|
|
1574
|
-
* const ctx = await
|
|
1623
|
+
* const ctx = await factory.prepare({ stage: "validate" });
|
|
1575
1624
|
* ctx.on("pipeline:success", (e) => console.log("done", e.finalState));
|
|
1576
1625
|
* const result = await ctx.run();
|
|
1577
1626
|
* ```
|
|
1578
1627
|
*/
|
|
1579
|
-
declare class
|
|
1628
|
+
declare class PipelineFactory<S extends object> {
|
|
1580
1629
|
private readonly definition;
|
|
1581
1630
|
private readonly logger;
|
|
1582
1631
|
private readonly storeFactory;
|
|
1583
1632
|
private readonly initialStateFactory;
|
|
1633
|
+
private readonly registry;
|
|
1584
1634
|
private readonly index;
|
|
1585
1635
|
/**
|
|
1586
|
-
* Constructs
|
|
1636
|
+
* Constructs a factory tied to a fixed pipeline definition.
|
|
1587
1637
|
*
|
|
1588
1638
|
* @param definition - The pipeline topology (stages, steps, routers).
|
|
1589
|
-
* @param options -
|
|
1639
|
+
* @param options - Factory configuration. `storeFactory` is mandatory.
|
|
1590
1640
|
*/
|
|
1591
|
-
constructor(definition: RoutingPipelineDefinition<S>, options:
|
|
1641
|
+
constructor(definition: RoutingPipelineDefinition<S>, options: PipelineFactoryOptions<S>);
|
|
1592
1642
|
/**
|
|
1593
1643
|
* Prepare an isolated {@link RunContext} for a **new** run.
|
|
1594
1644
|
*
|
|
@@ -1596,6 +1646,9 @@ declare class PipelineEngine<S extends object> {
|
|
|
1596
1646
|
* initial state from `initialStateFactory`. No execution occurs until
|
|
1597
1647
|
* `runContext.run()` is called.
|
|
1598
1648
|
*
|
|
1649
|
+
* If a registry is configured, the context and store are registered before
|
|
1650
|
+
* this method returns.
|
|
1651
|
+
*
|
|
1599
1652
|
* @param entry - Optional address describing where to start execution.
|
|
1600
1653
|
* Omit to start from the lowest‑order stage.
|
|
1601
1654
|
* @param runId - Optional run identifier (UUID v7). Generated if omitted.
|
|
@@ -1605,9 +1658,18 @@ declare class PipelineEngine<S extends object> {
|
|
|
1605
1658
|
/**
|
|
1606
1659
|
* Reconstruct a {@link RunContext} for a previously paused run.
|
|
1607
1660
|
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1661
|
+
* **Fast path (registry hit):** If a registry is configured and still holds
|
|
1662
|
+
* a live strong reference for `runId` (i.e. the pause timeout has not fired),
|
|
1663
|
+
* the existing RunContext is returned directly. No store read, no
|
|
1664
|
+
* ArtifactContainer.from() — zero serialization cost.
|
|
1665
|
+
*
|
|
1666
|
+
* **Slow path (store reconstruction):** If no live context exists (timeout
|
|
1667
|
+
* expired, process restarted, or no registry), the store is read, the
|
|
1668
|
+
* checkpoint is validated, and a fresh RunContext is built from the
|
|
1669
|
+
* containerBundle (if the registry wrote one at expiry) or from scratch.
|
|
1670
|
+
*
|
|
1671
|
+
* The context is registered with the registry before this method returns
|
|
1672
|
+
* (slow path only — the fast path context is already registered).
|
|
1611
1673
|
*
|
|
1612
1674
|
* @param runId - The identifier of the paused run.
|
|
1613
1675
|
* @returns A result containing the `RunContext`, or a failure if no
|
|
@@ -1619,7 +1681,7 @@ declare class PipelineEngine<S extends object> {
|
|
|
1619
1681
|
*
|
|
1620
1682
|
* This method is package-internal. External callers use prepare() or resume().
|
|
1621
1683
|
* Sub-pipelines access it through the {@link SubPipelineFactory} interface,
|
|
1622
|
-
* which is the only reference RunContextImpl holds to the
|
|
1684
|
+
* which is the only reference RunContextImpl holds to the factory.
|
|
1623
1685
|
*
|
|
1624
1686
|
* A single {@link ArtifactContainer} is created per run at root level and
|
|
1625
1687
|
* shared across all sub-pipelines. Steps are registered under namespaced keys
|
|
@@ -1630,16 +1692,41 @@ declare class PipelineEngine<S extends object> {
|
|
|
1630
1692
|
* threaded into {@link registerSteps} so that every step factory closure
|
|
1631
1693
|
* captures the correct signal at registration time.
|
|
1632
1694
|
*
|
|
1633
|
-
* @param runId
|
|
1634
|
-
* @param pipeline
|
|
1635
|
-
* @param entry
|
|
1636
|
-
* @param store
|
|
1637
|
-
* @param parentBus
|
|
1638
|
-
* @param parentPath
|
|
1639
|
-
* @param container
|
|
1640
|
-
* @param keyPrefix
|
|
1695
|
+
* @param runId - The run identifier (same for parent and sub‑pipelines).
|
|
1696
|
+
* @param pipeline - The pipeline (sub‑)definition.
|
|
1697
|
+
* @param entry - Entry address; `undefined` means start from the beginning.
|
|
1698
|
+
* @param store - The shared store instance for this run.
|
|
1699
|
+
* @param parentBus - Parent scoped bus for event bubbling (root runs pass undefined).
|
|
1700
|
+
* @param parentPath - Event path from the root.
|
|
1701
|
+
* @param container - Shared container (created once at root; passed down to sub-pipelines).
|
|
1702
|
+
* @param keyPrefix - Namespacing prefix for artifact keys within the shared container.
|
|
1703
|
+
* @param artifactBundle - Optional exported container state for store-based resume.
|
|
1641
1704
|
*/
|
|
1642
1705
|
buildRunContext(runId: string, pipeline: RoutingPipelineDefinition<S>, entry: EntryAddress | undefined, store: DataStore<S>, parentBus: ScopedEventBus<S> | undefined, parentPath: EventPath, container?: ArtifactContainer<Record<string, DeepPartial<S>>, S>, keyPrefix?: string, artifactBundle?: ExportedContainerState): Promise<RunContext<S>>;
|
|
1643
1706
|
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Writes a checkpoint into the store using the typed EngineStoreEnvelope.
|
|
1709
|
+
* The write is synchronous from the store's perspective (the transaction
|
|
1710
|
+
* boundary lives in the caller). No `any` cast is required because
|
|
1711
|
+
* EngineStoreEnvelope fully types the factory-internal key namespace.
|
|
1712
|
+
*
|
|
1713
|
+
* Exported so the PipelineRegistry can update an existing checkpoint with a
|
|
1714
|
+
* containerBundle at timeout expiry without duplicating the write logic.
|
|
1715
|
+
*/
|
|
1716
|
+
declare function writeCheckpoint(store: DataStore<any>, checkpoint: PipelineCheckpoint): Promise<void>;
|
|
1717
|
+
/**
|
|
1718
|
+
* Reads a checkpoint from the store using the typed EngineStoreEnvelope.
|
|
1719
|
+
* Returns null if no checkpoint exists for the given pipelineId / runId pair.
|
|
1720
|
+
* Synchronous — the store's get() is a synchronous snapshot read.
|
|
1721
|
+
*/
|
|
1722
|
+
declare function readCheckpoint(store: DataStore<any>, pipelineId: string | undefined, runId: string): PipelineCheckpoint | null;
|
|
1723
|
+
/**
|
|
1724
|
+
* Removes a checkpoint from the store.
|
|
1725
|
+
* Called by the registry when a paused run expires and no resume arrived,
|
|
1726
|
+
* after the containerBundle (if any) has been written into the checkpoint.
|
|
1727
|
+
* Exported so the registry can clear stale checkpoints without reaching into
|
|
1728
|
+
* the factory's internals.
|
|
1729
|
+
*/
|
|
1730
|
+
declare function clearCheckpoint(store: DataStore<any>, pipelineId: string, runId: string): Promise<void>;
|
|
1644
1731
|
|
|
1645
|
-
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition,
|
|
1732
|
+
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition, type PipelineEventMap, PipelineFactory, type PipelineFactoryOptions, type PipelineRegistryBinding, type PipelineRunResult, type PipelineStageRouter, type PipelineStep, type PipelineStepDefinition, Result, type RoutingInstruction, type RoutingPipelineDefinition, type RunContext, type RunEventHandler, type RunEventMap, SequentialExecutionContext, type Stage, type StageCarry, type State, type Step, type StepStageRouter, type SubPipelineAddress, clearCheckpoint, isPauseInstruction, readCheckpoint, writeCheckpoint };
|
package/index.d.ts
CHANGED
|
@@ -1182,22 +1182,27 @@ interface State {
|
|
|
1182
1182
|
[key: string]: any;
|
|
1183
1183
|
}
|
|
1184
1184
|
/**
|
|
1185
|
-
* Instructs the
|
|
1186
|
-
*
|
|
1185
|
+
* Instructs the factory to pause the pipeline.
|
|
1186
|
+
*
|
|
1187
|
+
* - `pause` — the `stageId` at which the pipeline should resume.
|
|
1188
|
+
* - `timeout` — how long (ms) the registry should hold the live RunContext
|
|
1189
|
+
* before running the deferred container export and clearing the
|
|
1190
|
+
* strong reference. Omit to use the registry's configured default.
|
|
1191
|
+
* A value of 0 means export immediately on pause (no deferral).
|
|
1192
|
+
* - `persist` — kept for backward compatibility; when true the registry will
|
|
1193
|
+
* always export the container bundle at expiry regardless of
|
|
1194
|
+
* whether resume was called. Ignored if timeout is 0.
|
|
1187
1195
|
*/
|
|
1188
1196
|
interface PauseInstruction {
|
|
1189
1197
|
readonly pause: string;
|
|
1190
|
-
|
|
1191
|
-
* If true, the engine will snapshot the entire ArtifactContainer
|
|
1192
|
-
* and store the bundle in the checkpoint. Defaults to false.
|
|
1193
|
-
*/
|
|
1198
|
+
readonly timeout?: number;
|
|
1194
1199
|
readonly persist?: boolean;
|
|
1195
1200
|
}
|
|
1196
1201
|
/**
|
|
1197
1202
|
* All possible outcomes of a router:
|
|
1198
|
-
* - `string`
|
|
1199
|
-
* - `null`
|
|
1200
|
-
* - `undefined`
|
|
1203
|
+
* - `string` → jump to a named stage
|
|
1204
|
+
* - `null` → terminate the pipeline
|
|
1205
|
+
* - `undefined` → advance to the next stage in order (or natural end)
|
|
1201
1206
|
* - `PauseInstruction` → suspend and write a checkpoint
|
|
1202
1207
|
*/
|
|
1203
1208
|
type RoutingInstruction = string | null | undefined | PauseInstruction;
|
|
@@ -1220,6 +1225,10 @@ type PipelineStageRouter<S extends object> = (state: S, results: Record<string,
|
|
|
1220
1225
|
*
|
|
1221
1226
|
* The checkpoint is always written atomically with the state patches of the
|
|
1222
1227
|
* stage that triggered the pause.
|
|
1228
|
+
*
|
|
1229
|
+
* `containerBundle` is intentionally absent at write time — the factory never
|
|
1230
|
+
* exports. The registry writes it into the checkpoint (via writeCheckpoint)
|
|
1231
|
+
* when the pause timeout fires and the live RunContext is about to be released.
|
|
1223
1232
|
*/
|
|
1224
1233
|
interface PipelineCheckpoint {
|
|
1225
1234
|
readonly runId: string;
|
|
@@ -1228,9 +1237,10 @@ interface PipelineCheckpoint {
|
|
|
1228
1237
|
readonly pausedAtStageId: string;
|
|
1229
1238
|
readonly pausedAtStageLabel: string;
|
|
1230
1239
|
readonly pausedOn: string;
|
|
1240
|
+
/** Written by the registry at timeout expiry, never by the factory. */
|
|
1231
1241
|
readonly containerBundle?: ExportedContainerState;
|
|
1232
1242
|
}
|
|
1233
|
-
/**
|
|
1243
|
+
/** Factory-internal namespace for all checkpoint data. */
|
|
1234
1244
|
declare const PIPELINE_DATA_KEY: "__pipeline_data__";
|
|
1235
1245
|
/**
|
|
1236
1246
|
* Run-scoped context injected into every step action as a second argument.
|
|
@@ -1391,10 +1401,14 @@ type EventPath = readonly PathNode[];
|
|
|
1391
1401
|
/**
|
|
1392
1402
|
* All events emitted during a run.
|
|
1393
1403
|
*
|
|
1394
|
-
* stage:paused (#
|
|
1404
|
+
* stage:paused (#8) is a dedicated event for stages that pause, distinct from
|
|
1395
1405
|
* stage:success. Consumers should listen to both if they want to react to all
|
|
1396
1406
|
* terminal stage outcomes. stage:success is only emitted when the stage
|
|
1397
1407
|
* advances (or terminates) — never when it pauses.
|
|
1408
|
+
*
|
|
1409
|
+
* pipeline:paused carries `pauseTimeout` forwarded from the PauseInstruction
|
|
1410
|
+
* so the PipelineRegistry can arm its cleanup timer with the correct duration
|
|
1411
|
+
* without re-reading or re-parsing the instruction.
|
|
1398
1412
|
*/
|
|
1399
1413
|
interface RunEventMap<S extends object> {
|
|
1400
1414
|
"pipeline:start": {
|
|
@@ -1417,6 +1431,12 @@ interface RunEventMap<S extends object> {
|
|
|
1417
1431
|
runId: string;
|
|
1418
1432
|
checkpoint: PipelineCheckpoint;
|
|
1419
1433
|
finalState: S;
|
|
1434
|
+
/**
|
|
1435
|
+
* The timeout value from the PauseInstruction, forwarded verbatim.
|
|
1436
|
+
* Undefined means the registry should use its configured default.
|
|
1437
|
+
* 0 means export immediately (no deferral window).
|
|
1438
|
+
*/
|
|
1439
|
+
pauseTimeout: number | undefined;
|
|
1420
1440
|
};
|
|
1421
1441
|
"pipeline:failure": {
|
|
1422
1442
|
path: EventPath;
|
|
@@ -1503,8 +1523,8 @@ interface ScopedEventBus<S extends object> {
|
|
|
1503
1523
|
on<K extends keyof RunEventMap<S>>(event: K, handler: RunEventHandler<S, K>): () => void;
|
|
1504
1524
|
}
|
|
1505
1525
|
/**
|
|
1506
|
-
* A unit of execution returned by {@link
|
|
1507
|
-
* {@link
|
|
1526
|
+
* A unit of execution returned by {@link PipelineFactory.prepare} or
|
|
1527
|
+
* {@link PipelineFactory.resume}.
|
|
1508
1528
|
*
|
|
1509
1529
|
* Subscribe to lifecycle events via {@link on}, abort via {@link abort}, and
|
|
1510
1530
|
* start execution with {@link run}.
|
|
@@ -1529,27 +1549,29 @@ interface RunContext<S extends object> {
|
|
|
1529
1549
|
*/
|
|
1530
1550
|
run(): Promise<Result<PipelineRunResult<S>>>;
|
|
1531
1551
|
}
|
|
1532
|
-
/** Minimal logger interface used by the
|
|
1552
|
+
/** Minimal logger interface used by the factory. */
|
|
1533
1553
|
interface EngineLogger {
|
|
1534
1554
|
info: (msg: string, ctx?: any) => void;
|
|
1535
1555
|
error: (msg: string, ctx?: any) => void;
|
|
1536
1556
|
}
|
|
1537
1557
|
/**
|
|
1538
|
-
* Configuration for {@link
|
|
1558
|
+
* Configuration for {@link PipelineFactory}.
|
|
1539
1559
|
*
|
|
1540
1560
|
* @typeParam S - The shape of the state managed by the pipeline.
|
|
1541
1561
|
*/
|
|
1542
|
-
interface
|
|
1562
|
+
interface PipelineFactoryOptions<S extends object = State> {
|
|
1543
1563
|
/** Logger (defaults to a no‑op). */
|
|
1544
1564
|
logger?: EngineLogger;
|
|
1545
1565
|
/**
|
|
1546
1566
|
* **Required.** A factory that, given a `runId`, returns a `DataStore<S>`.
|
|
1547
|
-
* The
|
|
1548
|
-
* isolated store instance.
|
|
1567
|
+
* The factory does **not** hold a global store; each run receives its own
|
|
1568
|
+
* isolated store instance from this function.
|
|
1549
1569
|
*
|
|
1550
|
-
* For a new run (`prepare`), the
|
|
1570
|
+
* For a new run (`prepare`), the function should return an empty store.
|
|
1551
1571
|
* For a resumed run (`resume`), it must return the **same** store that was
|
|
1552
1572
|
* used during the original run (so that state and checkpoints are preserved).
|
|
1573
|
+
*
|
|
1574
|
+
* The returned store is owned by the run, not by PipelineFactory.
|
|
1553
1575
|
*/
|
|
1554
1576
|
storeFactory: (runId: string) => Promise<DataStore<S>>;
|
|
1555
1577
|
/**
|
|
@@ -1558,37 +1580,65 @@ interface PipelineEngineOptions<S extends object = State> {
|
|
|
1558
1580
|
* If omitted, the store remains empty.
|
|
1559
1581
|
*/
|
|
1560
1582
|
initialStateFactory?: () => S;
|
|
1583
|
+
/**
|
|
1584
|
+
* Optional registry to register every RunContext with after construction.
|
|
1585
|
+
* When provided, prepare() and resume() call registry.register() before
|
|
1586
|
+
* returning, passing both the RunContext and the run's DataStore so the
|
|
1587
|
+
* registry can drive deferred export without needing a reference to the factory.
|
|
1588
|
+
*/
|
|
1589
|
+
registry?: PipelineRegistryBinding<S>;
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Narrow interface the factory uses to register runs with the registry.
|
|
1593
|
+
* Typed as an interface rather than the full PipelineRegistry class so that
|
|
1594
|
+
* the factory remains decoupled from the registry's full surface.
|
|
1595
|
+
*/
|
|
1596
|
+
interface PipelineRegistryBinding<S extends object> {
|
|
1597
|
+
register(context: RunContext<S>, store: DataStore<S>): void;
|
|
1598
|
+
/**
|
|
1599
|
+
* Called by resume() before constructing a new RunContext.
|
|
1600
|
+
* Returns the existing live RunContext if the registry still holds a strong
|
|
1601
|
+
* reference for this runId (i.e. the pause timeout has not yet fired).
|
|
1602
|
+
* Returns null if no live context exists and reconstruction is needed.
|
|
1603
|
+
*/
|
|
1604
|
+
getLiveContext(runId: string): RunContext<S> | null;
|
|
1561
1605
|
}
|
|
1562
1606
|
/**
|
|
1563
|
-
*
|
|
1607
|
+
* A pure factory for creating and resuming pipeline runs.
|
|
1608
|
+
*
|
|
1609
|
+
* PipelineFactory is stateless between runs. It holds only the pipeline
|
|
1610
|
+
* definition (topology), a storeFactory function, and an optional logger and
|
|
1611
|
+
* registry binding. It does not own any DataStore, timer, or live run state.
|
|
1564
1612
|
*
|
|
1565
1613
|
* @typeParam S - The shape of the state object.
|
|
1566
1614
|
*
|
|
1567
1615
|
* @example
|
|
1568
1616
|
* ```ts
|
|
1569
|
-
* const
|
|
1617
|
+
* const factory = new PipelineFactory(myDefinition, {
|
|
1570
1618
|
* storeFactory: (runId) => createMyStore(runId),
|
|
1571
1619
|
* initialStateFactory: () => ({ counter: 0 }),
|
|
1620
|
+
* registry: PipelineRegistry.default,
|
|
1572
1621
|
* });
|
|
1573
1622
|
*
|
|
1574
|
-
* const ctx = await
|
|
1623
|
+
* const ctx = await factory.prepare({ stage: "validate" });
|
|
1575
1624
|
* ctx.on("pipeline:success", (e) => console.log("done", e.finalState));
|
|
1576
1625
|
* const result = await ctx.run();
|
|
1577
1626
|
* ```
|
|
1578
1627
|
*/
|
|
1579
|
-
declare class
|
|
1628
|
+
declare class PipelineFactory<S extends object> {
|
|
1580
1629
|
private readonly definition;
|
|
1581
1630
|
private readonly logger;
|
|
1582
1631
|
private readonly storeFactory;
|
|
1583
1632
|
private readonly initialStateFactory;
|
|
1633
|
+
private readonly registry;
|
|
1584
1634
|
private readonly index;
|
|
1585
1635
|
/**
|
|
1586
|
-
* Constructs
|
|
1636
|
+
* Constructs a factory tied to a fixed pipeline definition.
|
|
1587
1637
|
*
|
|
1588
1638
|
* @param definition - The pipeline topology (stages, steps, routers).
|
|
1589
|
-
* @param options -
|
|
1639
|
+
* @param options - Factory configuration. `storeFactory` is mandatory.
|
|
1590
1640
|
*/
|
|
1591
|
-
constructor(definition: RoutingPipelineDefinition<S>, options:
|
|
1641
|
+
constructor(definition: RoutingPipelineDefinition<S>, options: PipelineFactoryOptions<S>);
|
|
1592
1642
|
/**
|
|
1593
1643
|
* Prepare an isolated {@link RunContext} for a **new** run.
|
|
1594
1644
|
*
|
|
@@ -1596,6 +1646,9 @@ declare class PipelineEngine<S extends object> {
|
|
|
1596
1646
|
* initial state from `initialStateFactory`. No execution occurs until
|
|
1597
1647
|
* `runContext.run()` is called.
|
|
1598
1648
|
*
|
|
1649
|
+
* If a registry is configured, the context and store are registered before
|
|
1650
|
+
* this method returns.
|
|
1651
|
+
*
|
|
1599
1652
|
* @param entry - Optional address describing where to start execution.
|
|
1600
1653
|
* Omit to start from the lowest‑order stage.
|
|
1601
1654
|
* @param runId - Optional run identifier (UUID v7). Generated if omitted.
|
|
@@ -1605,9 +1658,18 @@ declare class PipelineEngine<S extends object> {
|
|
|
1605
1658
|
/**
|
|
1606
1659
|
* Reconstruct a {@link RunContext} for a previously paused run.
|
|
1607
1660
|
*
|
|
1608
|
-
*
|
|
1609
|
-
*
|
|
1610
|
-
*
|
|
1661
|
+
* **Fast path (registry hit):** If a registry is configured and still holds
|
|
1662
|
+
* a live strong reference for `runId` (i.e. the pause timeout has not fired),
|
|
1663
|
+
* the existing RunContext is returned directly. No store read, no
|
|
1664
|
+
* ArtifactContainer.from() — zero serialization cost.
|
|
1665
|
+
*
|
|
1666
|
+
* **Slow path (store reconstruction):** If no live context exists (timeout
|
|
1667
|
+
* expired, process restarted, or no registry), the store is read, the
|
|
1668
|
+
* checkpoint is validated, and a fresh RunContext is built from the
|
|
1669
|
+
* containerBundle (if the registry wrote one at expiry) or from scratch.
|
|
1670
|
+
*
|
|
1671
|
+
* The context is registered with the registry before this method returns
|
|
1672
|
+
* (slow path only — the fast path context is already registered).
|
|
1611
1673
|
*
|
|
1612
1674
|
* @param runId - The identifier of the paused run.
|
|
1613
1675
|
* @returns A result containing the `RunContext`, or a failure if no
|
|
@@ -1619,7 +1681,7 @@ declare class PipelineEngine<S extends object> {
|
|
|
1619
1681
|
*
|
|
1620
1682
|
* This method is package-internal. External callers use prepare() or resume().
|
|
1621
1683
|
* Sub-pipelines access it through the {@link SubPipelineFactory} interface,
|
|
1622
|
-
* which is the only reference RunContextImpl holds to the
|
|
1684
|
+
* which is the only reference RunContextImpl holds to the factory.
|
|
1623
1685
|
*
|
|
1624
1686
|
* A single {@link ArtifactContainer} is created per run at root level and
|
|
1625
1687
|
* shared across all sub-pipelines. Steps are registered under namespaced keys
|
|
@@ -1630,16 +1692,41 @@ declare class PipelineEngine<S extends object> {
|
|
|
1630
1692
|
* threaded into {@link registerSteps} so that every step factory closure
|
|
1631
1693
|
* captures the correct signal at registration time.
|
|
1632
1694
|
*
|
|
1633
|
-
* @param runId
|
|
1634
|
-
* @param pipeline
|
|
1635
|
-
* @param entry
|
|
1636
|
-
* @param store
|
|
1637
|
-
* @param parentBus
|
|
1638
|
-
* @param parentPath
|
|
1639
|
-
* @param container
|
|
1640
|
-
* @param keyPrefix
|
|
1695
|
+
* @param runId - The run identifier (same for parent and sub‑pipelines).
|
|
1696
|
+
* @param pipeline - The pipeline (sub‑)definition.
|
|
1697
|
+
* @param entry - Entry address; `undefined` means start from the beginning.
|
|
1698
|
+
* @param store - The shared store instance for this run.
|
|
1699
|
+
* @param parentBus - Parent scoped bus for event bubbling (root runs pass undefined).
|
|
1700
|
+
* @param parentPath - Event path from the root.
|
|
1701
|
+
* @param container - Shared container (created once at root; passed down to sub-pipelines).
|
|
1702
|
+
* @param keyPrefix - Namespacing prefix for artifact keys within the shared container.
|
|
1703
|
+
* @param artifactBundle - Optional exported container state for store-based resume.
|
|
1641
1704
|
*/
|
|
1642
1705
|
buildRunContext(runId: string, pipeline: RoutingPipelineDefinition<S>, entry: EntryAddress | undefined, store: DataStore<S>, parentBus: ScopedEventBus<S> | undefined, parentPath: EventPath, container?: ArtifactContainer<Record<string, DeepPartial<S>>, S>, keyPrefix?: string, artifactBundle?: ExportedContainerState): Promise<RunContext<S>>;
|
|
1643
1706
|
}
|
|
1707
|
+
/**
|
|
1708
|
+
* Writes a checkpoint into the store using the typed EngineStoreEnvelope.
|
|
1709
|
+
* The write is synchronous from the store's perspective (the transaction
|
|
1710
|
+
* boundary lives in the caller). No `any` cast is required because
|
|
1711
|
+
* EngineStoreEnvelope fully types the factory-internal key namespace.
|
|
1712
|
+
*
|
|
1713
|
+
* Exported so the PipelineRegistry can update an existing checkpoint with a
|
|
1714
|
+
* containerBundle at timeout expiry without duplicating the write logic.
|
|
1715
|
+
*/
|
|
1716
|
+
declare function writeCheckpoint(store: DataStore<any>, checkpoint: PipelineCheckpoint): Promise<void>;
|
|
1717
|
+
/**
|
|
1718
|
+
* Reads a checkpoint from the store using the typed EngineStoreEnvelope.
|
|
1719
|
+
* Returns null if no checkpoint exists for the given pipelineId / runId pair.
|
|
1720
|
+
* Synchronous — the store's get() is a synchronous snapshot read.
|
|
1721
|
+
*/
|
|
1722
|
+
declare function readCheckpoint(store: DataStore<any>, pipelineId: string | undefined, runId: string): PipelineCheckpoint | null;
|
|
1723
|
+
/**
|
|
1724
|
+
* Removes a checkpoint from the store.
|
|
1725
|
+
* Called by the registry when a paused run expires and no resume arrived,
|
|
1726
|
+
* after the containerBundle (if any) has been written into the checkpoint.
|
|
1727
|
+
* Exported so the registry can clear stale checkpoints without reaching into
|
|
1728
|
+
* the factory's internals.
|
|
1729
|
+
*/
|
|
1730
|
+
declare function clearCheckpoint(store: DataStore<any>, pipelineId: string, runId: string): Promise<void>;
|
|
1644
1731
|
|
|
1645
|
-
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition,
|
|
1732
|
+
export { type EngineLogger, type EntryAddress, type EventPath, PIPELINE_DATA_KEY, type PathNode, type PauseInstruction, Pipeline, type PipelineCheckpoint, type PipelineContext, type PipelineDefinition, type PipelineEventMap, PipelineFactory, type PipelineFactoryOptions, type PipelineRegistryBinding, type PipelineRunResult, type PipelineStageRouter, type PipelineStep, type PipelineStepDefinition, Result, type RoutingInstruction, type RoutingPipelineDefinition, type RunContext, type RunEventHandler, type RunEventMap, SequentialExecutionContext, type Stage, type StageCarry, type State, type Step, type StepStageRouter, type SubPipelineAddress, clearCheckpoint, isPauseInstruction, readCheckpoint, writeCheckpoint };
|