@blokjs/runner 0.2.2 → 0.4.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.
- package/dist/Configuration.d.ts +18 -0
- package/dist/Configuration.js +151 -4
- package/dist/Configuration.js.map +1 -1
- package/dist/PayloadTooLargeError.d.ts +19 -0
- package/dist/PayloadTooLargeError.js +29 -0
- package/dist/PayloadTooLargeError.js.map +1 -0
- package/dist/RunCancelledError.d.ts +17 -0
- package/dist/RunCancelledError.js +25 -0
- package/dist/RunCancelledError.js.map +1 -0
- package/dist/RunnerSteps.js +330 -33
- package/dist/RunnerSteps.js.map +1 -1
- package/dist/SubworkflowNode.d.ts +75 -0
- package/dist/SubworkflowNode.js +221 -0
- package/dist/SubworkflowNode.js.map +1 -0
- package/dist/TriggerBase.d.ts +128 -0
- package/dist/TriggerBase.js +773 -4
- package/dist/TriggerBase.js.map +1 -1
- package/dist/WaitDispatchRequest.d.ts +38 -0
- package/dist/WaitDispatchRequest.js +13 -0
- package/dist/WaitDispatchRequest.js.map +1 -0
- package/dist/WaitNode.d.ts +23 -0
- package/dist/WaitNode.js +26 -0
- package/dist/WaitNode.js.map +1 -0
- package/dist/concurrency/ConcurrencyBackend.d.ts +61 -0
- package/dist/concurrency/ConcurrencyBackend.js +20 -0
- package/dist/concurrency/ConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/ConcurrencyLimitError.d.ts +37 -0
- package/dist/concurrency/ConcurrencyLimitError.js +16 -0
- package/dist/concurrency/ConcurrencyLimitError.js.map +1 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.d.ts +64 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.js +297 -0
- package/dist/concurrency/NatsKvConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/QueueExpiredError.d.ts +40 -0
- package/dist/concurrency/QueueExpiredError.js +15 -0
- package/dist/concurrency/QueueExpiredError.js.map +1 -0
- package/dist/concurrency/createConcurrencyBackend.d.ts +23 -0
- package/dist/concurrency/createConcurrencyBackend.js +34 -0
- package/dist/concurrency/createConcurrencyBackend.js.map +1 -0
- package/dist/concurrency/readConcurrencyConfig.d.ts +60 -0
- package/dist/concurrency/readConcurrencyConfig.js +60 -0
- package/dist/concurrency/readConcurrencyConfig.js.map +1 -0
- package/dist/idempotency/resolveIdempotencyKey.d.ts +20 -0
- package/dist/idempotency/resolveIdempotencyKey.js +37 -0
- package/dist/idempotency/resolveIdempotencyKey.js.map +1 -0
- package/dist/index.d.ts +23 -3
- package/dist/index.js +47 -2
- package/dist/index.js.map +1 -1
- package/dist/monitoring/ConcurrencyMetrics.d.ts +56 -0
- package/dist/monitoring/ConcurrencyMetrics.js +107 -0
- package/dist/monitoring/ConcurrencyMetrics.js.map +1 -0
- package/dist/monitoring/JanitorMetrics.d.ts +27 -0
- package/dist/monitoring/JanitorMetrics.js +48 -0
- package/dist/monitoring/JanitorMetrics.js.map +1 -0
- package/dist/scheduling/DebounceCoordinator.d.ts +88 -0
- package/dist/scheduling/DebounceCoordinator.js +141 -0
- package/dist/scheduling/DebounceCoordinator.js.map +1 -0
- package/dist/scheduling/DeferredDispatchSignal.d.ts +50 -0
- package/dist/scheduling/DeferredDispatchSignal.js +14 -0
- package/dist/scheduling/DeferredDispatchSignal.js.map +1 -0
- package/dist/scheduling/DeferredRunScheduler.d.ts +68 -0
- package/dist/scheduling/DeferredRunScheduler.js +154 -0
- package/dist/scheduling/DeferredRunScheduler.js.map +1 -0
- package/dist/scheduling/readSchedulingConfig.d.ts +24 -0
- package/dist/scheduling/readSchedulingConfig.js +52 -0
- package/dist/scheduling/readSchedulingConfig.js.map +1 -0
- package/dist/timeouts/StepTimeoutError.d.ts +22 -0
- package/dist/timeouts/StepTimeoutError.js +31 -0
- package/dist/timeouts/StepTimeoutError.js.map +1 -0
- package/dist/tracing/InMemoryRunStore.d.ts +28 -1
- package/dist/tracing/InMemoryRunStore.js +150 -0
- package/dist/tracing/InMemoryRunStore.js.map +1 -1
- package/dist/tracing/Janitor.d.ts +70 -0
- package/dist/tracing/Janitor.js +150 -0
- package/dist/tracing/Janitor.js.map +1 -0
- package/dist/tracing/PostgresRunStore.d.ts +30 -0
- package/dist/tracing/PostgresRunStore.js +435 -3
- package/dist/tracing/PostgresRunStore.js.map +1 -1
- package/dist/tracing/RunStore.d.ts +100 -1
- package/dist/tracing/RunTracker.d.ts +238 -9
- package/dist/tracing/RunTracker.js +571 -1
- package/dist/tracing/RunTracker.js.map +1 -1
- package/dist/tracing/SqliteRunStore.d.ts +23 -1
- package/dist/tracing/SqliteRunStore.js +405 -6
- package/dist/tracing/SqliteRunStore.js.map +1 -1
- package/dist/tracing/TraceRouter.d.ts +20 -2
- package/dist/tracing/TraceRouter.js +249 -5
- package/dist/tracing/TraceRouter.js.map +1 -1
- package/dist/tracing/sanitize.d.ts +11 -0
- package/dist/tracing/sanitize.js +29 -0
- package/dist/tracing/sanitize.js.map +1 -1
- package/dist/tracing/types.d.ts +348 -2
- package/dist/utils/createChildContext.d.ts +32 -0
- package/dist/utils/createChildContext.js +113 -0
- package/dist/utils/createChildContext.js.map +1 -0
- package/dist/workflow/WorkflowNormalizer.d.ts +29 -41
- package/dist/workflow/WorkflowNormalizer.js +182 -0
- package/dist/workflow/WorkflowNormalizer.js.map +1 -1
- package/dist/workflow/WorkflowRegistry.d.ts +64 -0
- package/dist/workflow/WorkflowRegistry.js +81 -0
- package/dist/workflow/WorkflowRegistry.js.map +1 -0
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Dashboard, MetricsResult, NodeRun, RunEvent, RunQuery, TraceLogEntry, WorkflowRun, WorkflowSummary } from "./types";
|
|
1
|
+
import type { CachedStepResult, ConcurrencySlotResult, Dashboard, MetricsResult, NodeRun, RunEvent, RunQuery, ScheduledDispatchRow, TraceLogEntry, WorkflowRun, WorkflowSummary } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* Storage abstraction for trace data.
|
|
4
4
|
*
|
|
@@ -31,8 +31,107 @@ export interface RunStore {
|
|
|
31
31
|
listDashboards(): Dashboard[];
|
|
32
32
|
deleteDashboard(dashboardId: string): boolean;
|
|
33
33
|
updateDashboard(dashboardId: string, updates: Partial<Dashboard>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Return every run whose `parentRunId` matches the given run id, sorted
|
|
36
|
+
* oldest-first. Used by Studio's "Sub-runs" list on a parent's run-detail
|
|
37
|
+
* page. Returns `[]` when the run has no children.
|
|
38
|
+
*/
|
|
39
|
+
getRunsByParent(parentRunId: string): WorkflowRun[];
|
|
34
40
|
clearAll(): number;
|
|
35
41
|
deleteRunsBefore(timestamp: number): number;
|
|
36
42
|
evictOldRuns(maxRuns: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Look up a previously-cached step result. Returns null on miss or
|
|
45
|
+
* when the entry has expired (expired entries are lazily purged on read).
|
|
46
|
+
*/
|
|
47
|
+
getIdempotencyCache(workflowName: string, stepId: string, key: string): CachedStepResult | null;
|
|
48
|
+
/**
|
|
49
|
+
* Store a step result keyed by (workflowName, stepId, key). Overwrites any
|
|
50
|
+
* previous entry for the same triple. Pass `expiresAt: null` for no TTL.
|
|
51
|
+
*/
|
|
52
|
+
setIdempotencyCache(workflowName: string, stepId: string, key: string, entry: CachedStepResult): void;
|
|
53
|
+
/**
|
|
54
|
+
* Delete every entry whose `expiresAt` is non-null and `<= now`. Returns
|
|
55
|
+
* the number of rows removed. Cheap to call periodically; safe under
|
|
56
|
+
* concurrent reads.
|
|
57
|
+
*/
|
|
58
|
+
purgeExpiredIdempotencyCache(now: number): number;
|
|
59
|
+
/**
|
|
60
|
+
* Try to acquire a slot for `(workflowName, concurrencyKey)`. Lazily
|
|
61
|
+
* purges expired leases for the same key first, then grants the slot
|
|
62
|
+
* iff `currentInFlight < concurrencyLimit`.
|
|
63
|
+
*
|
|
64
|
+
* Returns:
|
|
65
|
+
* `{ acquired: true, currentInFlight: <new count> }` on success
|
|
66
|
+
* `{ acquired: false, currentInFlight: <observed count> }` on denial
|
|
67
|
+
*
|
|
68
|
+
* The lease has a hard upper bound (`leaseExpiresAt` in ms since epoch).
|
|
69
|
+
* Callers MUST release the slot in a `finally` block; the lease is the
|
|
70
|
+
* crash-safety net for processes that die before release.
|
|
71
|
+
*/
|
|
72
|
+
acquireConcurrencySlot(workflowName: string, concurrencyKey: string, concurrencyLimit: number, runId: string, leaseExpiresAt: number): ConcurrencySlotResult;
|
|
73
|
+
/**
|
|
74
|
+
* Release a slot previously acquired by `runId`. Idempotent — releasing
|
|
75
|
+
* an unknown `runId` is a no-op (covers double-release races between
|
|
76
|
+
* the happy-path `finally` block and the lazy-purge fallback).
|
|
77
|
+
*/
|
|
78
|
+
releaseConcurrencySlot(workflowName: string, concurrencyKey: string, runId: string): void;
|
|
79
|
+
/**
|
|
80
|
+
* Delete every lease whose `expiresAt <= now`. Returns the number of
|
|
81
|
+
* rows removed. Cheap to call periodically (e.g. from a janitor task);
|
|
82
|
+
* the gate also lazy-purges per-key on every acquire call.
|
|
83
|
+
*/
|
|
84
|
+
purgeExpiredConcurrencySlots(now: number): number;
|
|
85
|
+
/**
|
|
86
|
+
* Snapshot of in-flight concurrency slots — used by the
|
|
87
|
+
* `/__blok/concurrency/state` endpoint and Studio's in-flight tile.
|
|
88
|
+
*
|
|
89
|
+
* Returns one entry per `(workflowName, concurrencyKey)` bucket with
|
|
90
|
+
* an array of currently-held leases (un-expired). Empty buckets are
|
|
91
|
+
* omitted. Sort order is unspecified — caller sorts as needed.
|
|
92
|
+
*/
|
|
93
|
+
getConcurrencySnapshot(now: number): Array<{
|
|
94
|
+
workflowName: string;
|
|
95
|
+
concurrencyKey: string;
|
|
96
|
+
leases: Array<{
|
|
97
|
+
runId: string;
|
|
98
|
+
expiresAt: number;
|
|
99
|
+
}>;
|
|
100
|
+
}>;
|
|
101
|
+
/**
|
|
102
|
+
* Persist a scheduled dispatch row, or replace an existing one with
|
|
103
|
+
* the same `runId` (debounce reset, queue re-defer). Idempotent.
|
|
104
|
+
*
|
|
105
|
+
* Called by `DeferredRunScheduler.schedule()` when a `persist` payload
|
|
106
|
+
* is provided. The row carries everything the trigger needs to
|
|
107
|
+
* reconstruct dispatch on boot.
|
|
108
|
+
*/
|
|
109
|
+
upsertScheduledDispatch(row: ScheduledDispatchRow): void;
|
|
110
|
+
/**
|
|
111
|
+
* Delete a scheduled dispatch row. Returns true when a row existed.
|
|
112
|
+
* Idempotent — safe to call on rows that have already been deleted
|
|
113
|
+
* (e.g. after the timer fires + cancel races).
|
|
114
|
+
*/
|
|
115
|
+
deleteScheduledDispatch(runId: string): boolean;
|
|
116
|
+
/**
|
|
117
|
+
* List scheduled dispatches, optionally filtered by trigger type
|
|
118
|
+
* and/or status. Used by trigger boot recovery (HttpTrigger) to
|
|
119
|
+
* find rows it owns.
|
|
120
|
+
*/
|
|
121
|
+
getScheduledDispatches(opts?: {
|
|
122
|
+
triggerType?: string;
|
|
123
|
+
status?: string;
|
|
124
|
+
}): ScheduledDispatchRow[];
|
|
125
|
+
/**
|
|
126
|
+
* Janitor sweep — delete every `scheduled_dispatches` row whose
|
|
127
|
+
* `expires_at` has elapsed (`expires_at IS NOT NULL AND expires_at < now`).
|
|
128
|
+
* Rows without a TTL are left alone (their owning runs may legitimately
|
|
129
|
+
* stay queued indefinitely). Returns the count of deleted rows.
|
|
130
|
+
*
|
|
131
|
+
* Forward-scheduled rows whose owning runs were deleted (orphan dispatch
|
|
132
|
+
* rows) get reaped on the next `HttpTrigger.recoverDispatches()` call,
|
|
133
|
+
* not here. This sweep only handles past-TTL rows.
|
|
134
|
+
*/
|
|
135
|
+
purgeExpiredScheduledDispatches(now: number): number;
|
|
37
136
|
close(): void;
|
|
38
137
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { ConcurrencyBackend } from "../concurrency/ConcurrencyBackend";
|
|
2
3
|
import type { RunStore } from "./RunStore";
|
|
3
|
-
import type { Dashboard, MetricsResult, NodeRun, RunEvent, StartNodeOptions, StartRunOptions, TraceLogEntry, WorkflowRun,
|
|
4
|
+
import type { ConcurrencySlotResult, Dashboard, MetricsResult, NodeRun, RunEvent, RunQuery, StartNodeOptions, StartRunOptions, TraceLogEntry, WorkflowRun, WorkflowSummary } from "./types";
|
|
4
5
|
/** Webhook registration for run event notifications. */
|
|
5
6
|
export interface Webhook {
|
|
6
7
|
id: string;
|
|
@@ -29,8 +30,237 @@ export declare class RunTracker extends EventEmitter {
|
|
|
29
30
|
startRun(opts: StartRunOptions): WorkflowRun;
|
|
30
31
|
completeRun(runId: string, data?: unknown): void;
|
|
31
32
|
failRun(runId: string, error: Error | unknown): void;
|
|
33
|
+
/**
|
|
34
|
+
* Tier 2 #6 — mark a run as throttled because the concurrency gate
|
|
35
|
+
* denied it before any step executed. Distinct from `failRun` because
|
|
36
|
+
* no step ran; nothing produced an error. Studio surfaces a Throttled
|
|
37
|
+
* badge and SSE subscribers see a granular `RUN_THROTTLED` event.
|
|
38
|
+
*/
|
|
39
|
+
markRunThrottled(runId: string, info: {
|
|
40
|
+
concurrencyKey: string;
|
|
41
|
+
concurrencyLimit: number;
|
|
42
|
+
currentInFlight: number;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* Tier 2 #6 follow-up — mark a run as queued because the concurrency
|
|
46
|
+
* gate denied it AND the trigger is configured with `onLimit: "queue"`.
|
|
47
|
+
* The run will be re-attempted after `scheduledAt`; `scheduledAt` is
|
|
48
|
+
* persisted on the run record so Studio can render a "queued · retries
|
|
49
|
+
* at <time>" badge.
|
|
50
|
+
*
|
|
51
|
+
* Distinct from `markRunThrottled` because queued runs WILL eventually
|
|
52
|
+
* execute (or stay queued indefinitely until a slot frees), while
|
|
53
|
+
* throttled runs are terminal and `failRun` semantics are skipped.
|
|
54
|
+
*
|
|
55
|
+
* Caller is responsible for actually scheduling the retry via
|
|
56
|
+
* `DeferredRunScheduler`. This method only flips status + emits the
|
|
57
|
+
* `RUN_QUEUED` event. Re-marking with a later `scheduledAt` updates
|
|
58
|
+
* the field (used when re-defer happens after a timer-fired re-acquire
|
|
59
|
+
* also fails).
|
|
60
|
+
*/
|
|
61
|
+
markRunQueued(runId: string, info: {
|
|
62
|
+
concurrencyKey: string;
|
|
63
|
+
concurrencyLimit: number;
|
|
64
|
+
currentInFlight: number;
|
|
65
|
+
scheduledAt: number;
|
|
66
|
+
}): void;
|
|
67
|
+
/**
|
|
68
|
+
* Tier 2 #5 — mark a run as `delayed`. Called immediately after
|
|
69
|
+
* `startRun` for runs that should be deferred. The run record carries
|
|
70
|
+
* `scheduledAt` (and optionally `expiresAt`) so Studio can render a
|
|
71
|
+
* "Delayed → fires at <time>" badge.
|
|
72
|
+
*
|
|
73
|
+
* Caller is responsible for actually scheduling the dispatch via
|
|
74
|
+
* `DeferredRunScheduler`. This method only flips status + emits the
|
|
75
|
+
* `RUN_DELAYED` event.
|
|
76
|
+
*/
|
|
77
|
+
markRunDelayed(runId: string, info: {
|
|
78
|
+
scheduledAt: number;
|
|
79
|
+
delayMs: number;
|
|
80
|
+
expiresAt?: number;
|
|
81
|
+
}): void;
|
|
82
|
+
/**
|
|
83
|
+
* Tier 2 #5 — mark a run as `expired` because its TTL was exceeded
|
|
84
|
+
* before dispatch. Distinct from `failed` (no step ran) and
|
|
85
|
+
* `cancelled` (operator action — TTL is automatic).
|
|
86
|
+
*/
|
|
87
|
+
markRunExpired(runId: string, info: {
|
|
88
|
+
expiresAt: number;
|
|
89
|
+
expiredAt: number;
|
|
90
|
+
}): void;
|
|
91
|
+
/**
|
|
92
|
+
* Tier 2 #7 — mark a run as `debounced`. In **leading** mode this is
|
|
93
|
+
* terminal: the ping was suppressed because a sibling fired
|
|
94
|
+
* immediately (`intoRunId` carries the sibling's id). In **trailing**
|
|
95
|
+
* mode this is transient: the same run is marked `debounced` while
|
|
96
|
+
* the timer is active and flips to `running` when the window closes
|
|
97
|
+
* (no separate transition method needed — `tracker` updates status
|
|
98
|
+
* directly via store before invoking the runner).
|
|
99
|
+
*/
|
|
100
|
+
markRunDebounced(runId: string, info: {
|
|
101
|
+
debounceKey: string;
|
|
102
|
+
mode: "leading" | "trailing";
|
|
103
|
+
intoRunId?: string;
|
|
104
|
+
pingCount?: number;
|
|
105
|
+
scheduledAt?: number;
|
|
106
|
+
}): void;
|
|
107
|
+
/**
|
|
108
|
+
* Tier 2 quick-wins — mark a run as `crashed` (uncaught exception,
|
|
109
|
+
* OOM, signal). Distinct from `failRun` because the failure was
|
|
110
|
+
* NOT a step's `process()` throwing — it was the runner itself
|
|
111
|
+
* giving up. Currently manual; call from custom triggers / ops
|
|
112
|
+
* harnesses when uncaught failures are detected.
|
|
113
|
+
*/
|
|
114
|
+
markRunCrashed(runId: string, info: {
|
|
115
|
+
error: Error | unknown;
|
|
116
|
+
}): void;
|
|
117
|
+
/**
|
|
118
|
+
* Tier 2 quick-wins follow-up — bulk-flip every run currently in
|
|
119
|
+
* `running` status to `crashed`. Returns the count flipped.
|
|
120
|
+
*
|
|
121
|
+
* Used by:
|
|
122
|
+
* - Process-level uncaught-exception handlers
|
|
123
|
+
* (`TriggerBase.installCrashHandlers`) — flip in-flight runs
|
|
124
|
+
* before the process dies.
|
|
125
|
+
* - Boot recovery (`TriggerBase.recoverOrphanedRuns`) — flip runs
|
|
126
|
+
* that were `running` from the previous (dead) process.
|
|
127
|
+
*
|
|
128
|
+
* Synchronous + safe to call from a `process.on("uncaughtException")`
|
|
129
|
+
* handler (which can't await). Backed by sync sqlite/in-memory
|
|
130
|
+
* writes that complete before the handler returns.
|
|
131
|
+
*
|
|
132
|
+
* Optional `opts.maxStartedAt` filter — only flip runs whose
|
|
133
|
+
* `startedAt` is at or before this timestamp. Used by boot recovery
|
|
134
|
+
* to avoid flipping runs from the current (live) process.
|
|
135
|
+
*/
|
|
136
|
+
markAllRunningRunsAsCrashed(error: Error | unknown, opts?: {
|
|
137
|
+
maxStartedAt?: number;
|
|
138
|
+
}): number;
|
|
139
|
+
/**
|
|
140
|
+
* Tier 2 quick-wins — mark a run as `timedOut` because a step's
|
|
141
|
+
* final retry attempt exceeded its `maxDuration` cap. Distinct
|
|
142
|
+
* from `failed` so SLA dashboards can separate timeout-driven
|
|
143
|
+
* failures (network / capacity) from logic failures (bugs).
|
|
144
|
+
* Auto-called by `RunnerSteps` on final-attempt `StepTimeoutError`.
|
|
145
|
+
*/
|
|
146
|
+
markRunTimedOut(runId: string, info: {
|
|
147
|
+
stepId: string;
|
|
148
|
+
maxDurationMs: number;
|
|
149
|
+
attemptsExhausted: number;
|
|
150
|
+
}): void;
|
|
151
|
+
/**
|
|
152
|
+
* Tier 2 #7 — record an additional ping into an existing trailing-mode
|
|
153
|
+
* debounce window. Increments `pingCount` and updates `scheduledAt`.
|
|
154
|
+
* Does NOT emit a new event (avoid event-stream bloat under burst).
|
|
155
|
+
*/
|
|
156
|
+
recordDebouncePing(runId: string, opts: {
|
|
157
|
+
pingCount: number;
|
|
158
|
+
scheduledAt: number;
|
|
159
|
+
}): void;
|
|
160
|
+
/**
|
|
161
|
+
* Tier 2 #7 — transition a `delayed`/`debounced` run into `running`
|
|
162
|
+
* when its timer fires. Studio sees the status change via the
|
|
163
|
+
* existing run-update SSE stream.
|
|
164
|
+
*/
|
|
165
|
+
transitionRunToRunning(runId: string): void;
|
|
166
|
+
/**
|
|
167
|
+
* Tier 2 polish — cancel a pending (delayed/debounced/queued) run.
|
|
168
|
+
* Idempotent. Returns true when the run existed AND was in a cancellable
|
|
169
|
+
* state; false when the run doesn't exist OR is already running/completed/
|
|
170
|
+
* failed/throttled/expired/crashed/timedOut/cancelled.
|
|
171
|
+
*
|
|
172
|
+
* **Caller responsibility**: this method only updates the run record
|
|
173
|
+
* (status → `"cancelled"`) and emits `RUN_CANCELLED`. The caller must
|
|
174
|
+
* separately clear any pending scheduler timers via
|
|
175
|
+
* `DeferredRunScheduler.getInstance().cancel(runId)` and (when applicable)
|
|
176
|
+
* `DebounceCoordinator.getInstance().cancel(workflowName, debounceKey)`.
|
|
177
|
+
* Done this way to avoid an import cycle from tracing → scheduling.
|
|
178
|
+
*/
|
|
179
|
+
cancelRun(runId: string, options?: {
|
|
180
|
+
cascade?: boolean;
|
|
181
|
+
}): boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Per-process map from runId to the AbortController owned by the
|
|
184
|
+
* trigger's createContext call. Populated by TriggerBase right after
|
|
185
|
+
* `startRun()`; cleared in TriggerBase's finally block. Used by
|
|
186
|
+
* `abortRunningRun` to fire the signal when an operator cancels a
|
|
187
|
+
* `running` run via the cancel API.
|
|
188
|
+
*/
|
|
189
|
+
private abortControllers;
|
|
190
|
+
registerAbortController(runId: string, controller: AbortController): void;
|
|
191
|
+
unregisterAbortController(runId: string): void;
|
|
192
|
+
/**
|
|
193
|
+
* Tier 2 follow-up · cooperative cancellation for `running` runs.
|
|
194
|
+
*
|
|
195
|
+
* Fires the run's AbortController (so `ctx.signal.aborted` becomes
|
|
196
|
+
* true and any node consulting it can abort early) AND flips the run
|
|
197
|
+
* status to `"cancelled"` immediately via `cancelRun`. RunnerSteps'
|
|
198
|
+
* between-step abort check throws `RunCancelledError` shortly after,
|
|
199
|
+
* which TriggerBase catches without re-flipping the status.
|
|
200
|
+
*
|
|
201
|
+
* Returns true when an AbortController was registered for this run
|
|
202
|
+
* AND the status was successfully flipped; false otherwise (run not
|
|
203
|
+
* found, run not in `running` status, or no controller registered —
|
|
204
|
+
* e.g. controller already cleaned up).
|
|
205
|
+
*/
|
|
206
|
+
abortRunningRun(runId: string): boolean;
|
|
207
|
+
/**
|
|
208
|
+
* Tier 2 #6 follow-up · cross-process concurrency backend.
|
|
209
|
+
*
|
|
210
|
+
* When set (via {@link setConcurrencyBackend}), the tracker's
|
|
211
|
+
* `acquireConcurrencySlot` and `releaseConcurrencySlot` methods
|
|
212
|
+
* delegate to the backend instead of the local sync `RunStore` impl.
|
|
213
|
+
* Used to coordinate across processes via NATS KV / Redis.
|
|
214
|
+
*
|
|
215
|
+
* Default `null` — preserves zero-overhead in-process behavior.
|
|
216
|
+
* Trigger packages install a backend in `listen()` when the operator
|
|
217
|
+
* sets `BLOK_CONCURRENCY_BACKEND=nats-kv`.
|
|
218
|
+
*/
|
|
219
|
+
private concurrencyBackend;
|
|
220
|
+
setConcurrencyBackend(backend: ConcurrencyBackend | null): void;
|
|
221
|
+
getConcurrencyBackend(): ConcurrencyBackend | null;
|
|
222
|
+
/**
|
|
223
|
+
* Acquire a concurrency slot for `(workflowName, concurrencyKey)`.
|
|
224
|
+
* Delegates to the configured cross-process backend when set; falls
|
|
225
|
+
* back to the local sync `RunStore` impl otherwise.
|
|
226
|
+
*
|
|
227
|
+
* Async — the cross-process backend (NATS KV) is async-only. The
|
|
228
|
+
* sync fallback is wrapped in `Promise.resolve()` so the call site
|
|
229
|
+
* is uniform.
|
|
230
|
+
*/
|
|
231
|
+
acquireConcurrencySlot(workflowName: string, concurrencyKey: string, concurrencyLimit: number, runId: string, leaseExpiresAt: number): Promise<ConcurrencySlotResult>;
|
|
232
|
+
/** Release a slot acquired via `acquireConcurrencySlot`. Idempotent. */
|
|
233
|
+
releaseConcurrencySlot(workflowName: string, concurrencyKey: string, runId: string): Promise<void>;
|
|
32
234
|
startNode(runId: string, opts: StartNodeOptions): NodeRun;
|
|
33
235
|
completeNode(nodeRunId: string, outputs?: unknown, nodeMetrics?: NodeRun["metrics"]): void;
|
|
236
|
+
/**
|
|
237
|
+
* Tier 1 idempotency cache hit. Marks the node as completed without
|
|
238
|
+
* having actually run, attaches the source-run/source-node lineage so
|
|
239
|
+
* Studio can render a CACHED badge with click-through, and emits a
|
|
240
|
+
* `NODE_CACHED` event so SSE subscribers see the short-circuit live.
|
|
241
|
+
*
|
|
242
|
+
* Caller is responsible for replaying the cached result through
|
|
243
|
+
* `PersistenceHelper.applyStepOutput` — this method only records the
|
|
244
|
+
* tracing side. Caching layers ABOVE persistence, never within it.
|
|
245
|
+
*/
|
|
246
|
+
markNodeCached(nodeRunId: string, source: {
|
|
247
|
+
sourceRunId: string;
|
|
248
|
+
sourceNodeRunId: string;
|
|
249
|
+
cachedAt: number;
|
|
250
|
+
}, outputs?: unknown): void;
|
|
251
|
+
/**
|
|
252
|
+
* Tier 1 retry: record a single failed attempt before the next retry. The
|
|
253
|
+
* node stays in `running` status — `failNode` is the terminal call that
|
|
254
|
+
* fires only after `retry.maxAttempts` is exhausted.
|
|
255
|
+
*
|
|
256
|
+
* Per-node attempt history is capped at {@link MAX_STORED_ATTEMPTS} (10)
|
|
257
|
+
* to bound store growth on extreme retry counts. The cap matches the
|
|
258
|
+
* risk-register decision in `tier1-idempotency-replay-retry.md`.
|
|
259
|
+
*/
|
|
260
|
+
recordNodeAttemptFailed(nodeRunId: string, info: {
|
|
261
|
+
attempt: number;
|
|
262
|
+
error: unknown;
|
|
263
|
+
}): void;
|
|
34
264
|
failNode(nodeRunId: string, error: Error | unknown): void;
|
|
35
265
|
skipNode(runId: string, nodeName: string, stepIndex: number, reason?: string): void;
|
|
36
266
|
/**
|
|
@@ -57,20 +287,19 @@ export declare class RunTracker extends EventEmitter {
|
|
|
57
287
|
addLog(entry: Omit<TraceLogEntry, "id" | "timestamp">): void;
|
|
58
288
|
trackVarsUpdate(runId: string, nodeName: string, nodeId: string | undefined, vars: Record<string, unknown>): void;
|
|
59
289
|
getRun(runId: string): WorkflowRun | undefined;
|
|
60
|
-
getRuns(opts?: {
|
|
61
|
-
workflow?: string;
|
|
62
|
-
status?: WorkflowRunStatus;
|
|
63
|
-
tags?: string[];
|
|
64
|
-
limit?: number;
|
|
65
|
-
offset?: number;
|
|
66
|
-
sort?: "asc" | "desc";
|
|
67
|
-
}): {
|
|
290
|
+
getRuns(opts?: RunQuery): {
|
|
68
291
|
runs: WorkflowRun[];
|
|
69
292
|
total: number;
|
|
70
293
|
};
|
|
71
294
|
getNodeRuns(runId: string): NodeRun[];
|
|
72
295
|
getNodeRun(nodeRunId: string): NodeRun | undefined;
|
|
73
296
|
getEvents(runId: string, since?: number): RunEvent[];
|
|
297
|
+
/**
|
|
298
|
+
* Tier 2 sub-workflow lineage. Returns every run that was started by
|
|
299
|
+
* a `subworkflow:` step inside the given parent run. Powers Studio's
|
|
300
|
+
* "Sub-runs" list on a parent's run-detail page.
|
|
301
|
+
*/
|
|
302
|
+
getRunsByParent(parentRunId: string): WorkflowRun[];
|
|
74
303
|
getLogs(runId: string, nodeId?: string): TraceLogEntry[];
|
|
75
304
|
getWorkflowSummaries(): WorkflowSummary[];
|
|
76
305
|
addTag(runId: string, tag: string): boolean;
|