@substrat-run/kernel 0.135.0 → 0.137.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/async-invocation-log.d.ts +61 -0
- package/dist/async-invocation-log.d.ts.map +1 -0
- package/dist/async-invocation-log.js +149 -0
- package/dist/async-invocation-log.js.map +1 -0
- package/dist/base64url.d.ts +6 -0
- package/dist/base64url.d.ts.map +1 -0
- package/dist/base64url.js +19 -0
- package/dist/base64url.js.map +1 -0
- package/dist/capability.d.ts +4 -0
- package/dist/capability.d.ts.map +1 -1
- package/dist/capability.js +7 -8
- package/dist/capability.js.map +1 -1
- package/dist/carried-copy.d.ts +117 -0
- package/dist/carried-copy.d.ts.map +1 -0
- package/dist/carried-copy.js +134 -0
- package/dist/carried-copy.js.map +1 -0
- package/dist/index.d.ts +101 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -14
- package/dist/index.js.map +1 -1
- package/dist/invocation-log.d.ts +115 -9
- package/dist/invocation-log.d.ts.map +1 -1
- package/dist/invocation-log.js +78 -15
- package/dist/invocation-log.js.map +1 -1
- package/dist/job-run.d.ts +77 -15
- package/dist/job-run.d.ts.map +1 -1
- package/dist/job-run.js +107 -24
- package/dist/job-run.js.map +1 -1
- package/dist/lifecycle-flow.d.ts.map +1 -1
- package/dist/lifecycle-flow.js +2 -1
- package/dist/lifecycle-flow.js.map +1 -1
- package/dist/list-index.d.ts +19 -4
- package/dist/list-index.d.ts.map +1 -1
- package/dist/list-index.js +150 -8
- package/dist/list-index.js.map +1 -1
- package/dist/permission-eval.d.ts +9 -0
- package/dist/permission-eval.d.ts.map +1 -1
- package/dist/permission-eval.js +26 -0
- package/dist/permission-eval.js.map +1 -1
- package/dist/platform-call.d.ts +4 -37
- package/dist/platform-call.d.ts.map +1 -1
- package/dist/platform-call.js +5 -37
- package/dist/platform-call.js.map +1 -1
- package/dist/platform-sweep.d.ts +17 -0
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +22 -4
- package/dist/platform-sweep.js.map +1 -1
- package/dist/provider-error.d.ts.map +1 -1
- package/dist/provider-error.js +2 -1
- package/dist/provider-error.js.map +1 -1
- package/dist/refusal-query.d.ts +4 -1
- package/dist/refusal-query.d.ts.map +1 -1
- package/dist/refusal-query.js +6 -4
- package/dist/refusal-query.js.map +1 -1
- package/dist/refusals.d.ts +80 -8
- package/dist/refusals.d.ts.map +1 -1
- package/dist/refusals.js +141 -22
- package/dist/refusals.js.map +1 -1
- package/dist/routed-node.d.ts +3 -2
- package/dist/routed-node.d.ts.map +1 -1
- package/dist/routed-node.js.map +1 -1
- package/dist/scope-copy.d.ts +122 -0
- package/dist/scope-copy.d.ts.map +1 -0
- package/dist/scope-copy.js +187 -0
- package/dist/scope-copy.js.map +1 -0
- package/dist/scope-host.d.ts +95 -27
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +5 -14
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-lifecycle.d.ts +70 -0
- package/dist/scope-lifecycle.d.ts.map +1 -0
- package/dist/scope-lifecycle.js +124 -0
- package/dist/scope-lifecycle.js.map +1 -0
- package/dist/system-switch-record.d.ts +27 -11
- package/dist/system-switch-record.d.ts.map +1 -1
- package/dist/system-switch-record.js +59 -24
- package/dist/system-switch-record.js.map +1 -1
- package/dist/system-switch.d.ts +41 -11
- package/dist/system-switch.d.ts.map +1 -1
- package/dist/system-switch.js +48 -15
- package/dist/system-switch.js.map +1 -1
- package/package.json +2 -2
package/dist/invocation-log.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export interface InvocationRecord {
|
|
|
87
87
|
emitted?: EmittedReport;
|
|
88
88
|
/**
|
|
89
89
|
* #1331: which of the operation's DECLARED output fields its response carried. Filled
|
|
90
|
-
* only
|
|
90
|
+
* only on a request the router armed the walk for ({@link fieldCoverageArmed}), and absent
|
|
91
91
|
* otherwise — never an empty report, so "not walked" cannot read as "returned nothing".
|
|
92
92
|
*/
|
|
93
93
|
outputFields?: OutputFieldsReport;
|
|
@@ -115,11 +115,12 @@ export { invocationLevelOf, type InvocationLevel } from '@substrat-run/contracts
|
|
|
115
115
|
* its scope host as `VerticalScopeHost` rather than importing a concrete adapter: the
|
|
116
116
|
* seam is the shape, not the vendor.
|
|
117
117
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
118
|
+
* This line belongs with the router-assertion family (`readRoutedNode`,
|
|
119
|
+
* `assertPlatformCall`) — the code that reads what the router asserted about a request —
|
|
120
|
+
* because it is the same family seen from the other end: it writes that assertion down so
|
|
121
|
+
* a reader can find it again. The family is moving from the kernel to `vertical-host`
|
|
122
|
+
* (#1978), which already re-exports it; `vertical-host` keeps its AI SDK behind the
|
|
123
|
+
* `./model` subpath, so a vertical importing this from its root bundles none of it.
|
|
123
124
|
*/
|
|
124
125
|
export interface InvocationLogContext<Env = unknown> {
|
|
125
126
|
req: {
|
|
@@ -183,6 +184,14 @@ export interface InvocationLogOptions<Env = unknown> {
|
|
|
183
184
|
export interface InvocationLogLine {
|
|
184
185
|
/** Discriminator — what lets a reader tell this line from a vertical's own output. */
|
|
185
186
|
substrat: 'invocation';
|
|
187
|
+
/**
|
|
188
|
+
* #1901: what kind of work the line is about. ABSENT on a request's line — the line every
|
|
189
|
+
* reader already knew — and present only on the scope host's lines for async work: a
|
|
190
|
+
* consumer delivery (`consumer`) or a schedule run (`schedule`). A reader treats a missing
|
|
191
|
+
* `kind` as `request`, which keeps every line written before this field existed meaning
|
|
192
|
+
* what it meant.
|
|
193
|
+
*/
|
|
194
|
+
kind?: AsyncInvocationKind;
|
|
186
195
|
tenantId: string;
|
|
187
196
|
scopeId: string | null;
|
|
188
197
|
vertical: string | null;
|
|
@@ -192,9 +201,10 @@ export interface InvocationLogLine {
|
|
|
192
201
|
* null only this writer would produce — one representation across the platform.
|
|
193
202
|
*/
|
|
194
203
|
surface: string | null;
|
|
195
|
-
method
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
/** The request's method. `null` on an async line (#1901), which no request carried. */
|
|
205
|
+
method: string | null;
|
|
206
|
+
/** Path ONLY — see `pathOf`. `null` on an async line (#1901). */
|
|
207
|
+
path: string | null;
|
|
198
208
|
/**
|
|
199
209
|
* #1237: the id every event this invocation emitted is stamped with.
|
|
200
210
|
*
|
|
@@ -220,6 +230,9 @@ export interface InvocationLogLine {
|
|
|
220
230
|
*
|
|
221
231
|
* `null` therefore survives only for a genuine escape: an error that got past the
|
|
222
232
|
* envelope itself, which `threw` marks.
|
|
233
|
+
*
|
|
234
|
+
* Always `null` on an async line (#1901): no caller received a status. Its `outcome` and
|
|
235
|
+
* `level` say how it ended instead.
|
|
223
236
|
*/
|
|
224
237
|
status: number | null;
|
|
225
238
|
/** The error escaped even `onError` — rare, and the most interesting line on the page. */
|
|
@@ -259,7 +272,85 @@ export interface InvocationLogLine {
|
|
|
259
272
|
* existed. A reader treats absence exactly as it treats `null` elsewhere.
|
|
260
273
|
*/
|
|
261
274
|
outputFields?: OutputFieldsReport;
|
|
275
|
+
/**
|
|
276
|
+
* #1923: the router's dispatch id for the request whose response {@link outputFields}
|
|
277
|
+
* describes — its provenance. Present exactly when `outputFields` is: a reader joins it to
|
|
278
|
+
* the router's own line for the request, and counts the report only for the tenant and app
|
|
279
|
+
* that line names.
|
|
280
|
+
*/
|
|
281
|
+
fieldCoverageId?: string;
|
|
282
|
+
/** How the unit ended — see {@link AsyncOutcome}. */
|
|
283
|
+
outcome?: AsyncOutcome;
|
|
284
|
+
/** A consumer's event type. */
|
|
285
|
+
eventType?: string | null;
|
|
286
|
+
/** A consumer's event id — the join to the spine's outbox and delivery journal. */
|
|
287
|
+
eventId?: string | null;
|
|
288
|
+
/** Which attempt at this delivery the line is about, counting from 1. */
|
|
289
|
+
attempt?: number | null;
|
|
290
|
+
/** A schedule run's due time (ISO 8601), or `null` for a schedule's first run. */
|
|
291
|
+
dueAt?: string | null;
|
|
292
|
+
/** How late the run started against `dueAt`, in milliseconds; `null` on a first run. */
|
|
293
|
+
latenessMs?: number | null;
|
|
294
|
+
/** A `suppressed` line's count of the lines the pass's cap withheld. */
|
|
295
|
+
suppressed?: number;
|
|
296
|
+
/** The same count per `<kind>:<outcome>`, so a storm of one outcome is named, not averaged. */
|
|
297
|
+
suppressedBy?: Record<string, number>;
|
|
262
298
|
}
|
|
299
|
+
/** #1901: the kinds of async work a scope host writes a line for. A request has no `kind`. */
|
|
300
|
+
export type AsyncInvocationKind = 'consumer' | 'schedule';
|
|
301
|
+
/**
|
|
302
|
+
* #1901: how a unit of async work ended.
|
|
303
|
+
*
|
|
304
|
+
* - `delivered` — a consumer's handler ran and its delivery is journaled done.
|
|
305
|
+
* - `retrying` — the handler threw and the delivery is due again later.
|
|
306
|
+
* - `dead-lettered` — the delivery is journaled failed for good: the handler threw on its
|
|
307
|
+
* last attempt, or the event never reached it (undecodable, a schema version the consumer
|
|
308
|
+
* does not take, withheld by the producer).
|
|
309
|
+
* - `inert` — a copy of a scope (#2005): the delivery is journaled terminal and NO handler
|
|
310
|
+
* ran. Never `delivered`, because nothing was.
|
|
311
|
+
* - `routed` — the delivery was handed to the platform's drain to run with authority this
|
|
312
|
+
* host lacks (a connector on a control-plane-less host).
|
|
313
|
+
* - `ok` / `failed` — a schedule run.
|
|
314
|
+
* - `suppressed` — the pass's line cap was reached; the line counts what it withheld.
|
|
315
|
+
*/
|
|
316
|
+
export type AsyncOutcome = 'delivered' | 'retrying' | 'dead-lettered' | 'inert' | 'routed' | 'ok' | 'failed' | 'suppressed';
|
|
317
|
+
/**
|
|
318
|
+
* The fields of an invocation line, before defaults. The ONE place the line's grammar lives
|
|
319
|
+
* (#1901): the request writer below and the scope host's async writer both build through
|
|
320
|
+
* {@link invocationLine}, so a field added to one is a field added to both, in one order.
|
|
321
|
+
*/
|
|
322
|
+
export interface InvocationLineFields {
|
|
323
|
+
kind?: AsyncInvocationKind;
|
|
324
|
+
tenantId: string;
|
|
325
|
+
scopeId: string | null;
|
|
326
|
+
vertical?: string | null;
|
|
327
|
+
surface?: string | null;
|
|
328
|
+
method?: string | null;
|
|
329
|
+
path?: string | null;
|
|
330
|
+
invocationId: string;
|
|
331
|
+
status?: number | null;
|
|
332
|
+
threw: boolean;
|
|
333
|
+
durationMs: number;
|
|
334
|
+
level: InvocationLevel;
|
|
335
|
+
operation?: string | null;
|
|
336
|
+
problemCode?: string | null;
|
|
337
|
+
principalKind?: string | null;
|
|
338
|
+
emitted?: EmittedReport;
|
|
339
|
+
/**
|
|
340
|
+
* #1901: write `entities` from `emitted` (the default). An async line passes `false`: an
|
|
341
|
+
* entity id is data a vertical chose — an email, a customer number — and the async line
|
|
342
|
+
* carries ids the platform minted, declared names and codes only. Its `entities` is then
|
|
343
|
+
* always `[]`, which a reader takes as "not recorded" beside a non-null `eventCount`.
|
|
344
|
+
*/
|
|
345
|
+
withEntities?: boolean;
|
|
346
|
+
versionId?: string | null;
|
|
347
|
+
outputFields?: OutputFieldsReport;
|
|
348
|
+
/** #1923: written only beside `outputFields`. */
|
|
349
|
+
fieldCoverageId?: string;
|
|
350
|
+
async?: Pick<InvocationLogLine, 'outcome' | 'eventType' | 'eventId' | 'attempt' | 'dueAt' | 'latenessMs' | 'suppressed' | 'suppressedBy'>;
|
|
351
|
+
}
|
|
352
|
+
/** Build a line. Unfilled fields are `null` (or empty), as the line's contract says. */
|
|
353
|
+
export declare function invocationLine(f: InvocationLineFields): InvocationLogLine;
|
|
263
354
|
/**
|
|
264
355
|
* #1893: one request's stamp — the id minted for it and the record the handler chain fills
|
|
265
356
|
* in — shared by whichever layer started it.
|
|
@@ -267,6 +358,12 @@ export interface InvocationLogLine {
|
|
|
267
358
|
export interface InvocationStamp {
|
|
268
359
|
invocationId: string;
|
|
269
360
|
record: InvocationRecord;
|
|
361
|
+
/**
|
|
362
|
+
* #1923: the dispatch id the router armed this request's field walk with, when it did and
|
|
363
|
+
* the request's router assertion verified. Decided once, when the stamp begins — see
|
|
364
|
+
* {@link armedFieldCoverageId}. Written on the line beside the report, as its provenance.
|
|
365
|
+
*/
|
|
366
|
+
fieldCoverageId?: string;
|
|
270
367
|
}
|
|
271
368
|
/**
|
|
272
369
|
* The stamp a request already carries, if a layer outside this one started it (#1893).
|
|
@@ -274,6 +371,15 @@ export interface InvocationStamp {
|
|
|
274
371
|
* the case when the platform's entry stamped the request and the vertical mounts nothing.
|
|
275
372
|
*/
|
|
276
373
|
export declare function invocationStampOf(request: object): InvocationStamp | undefined;
|
|
374
|
+
/**
|
|
375
|
+
* #1923: whether the per-response field walk is armed for this request — the one question the
|
|
376
|
+
* walk's two callers in `vertical-host` (the operation routes and the MCP door) ask.
|
|
377
|
+
*
|
|
378
|
+
* `false` for a request no stamp covers, and for a stamp begun by a layer that predates the
|
|
379
|
+
* switch: every version skew between the platform's entry and a vertical's bundled kernel
|
|
380
|
+
* reads as off, never as on.
|
|
381
|
+
*/
|
|
382
|
+
export declare function fieldCoverageArmed(request: object): boolean;
|
|
277
383
|
/**
|
|
278
384
|
* Mount as the FIRST middleware on a vertical's app, with the same two answers the
|
|
279
385
|
* vertical gives `readRoutedNode` in its own `nodeFor`:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invocation-log.d.ts","sourceRoot":"","sources":["../src/invocation-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"invocation-log.d.ts","sourceRoot":"","sources":["../src/invocation-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAGH,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,iGAAiG;IACjG,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAID,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAEpG;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,oBAAoB,CAAC,GAAG,GAAG,OAAO;IACjD,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,YAAY,CAAA;SAAE,CAAA;KAAE,CAAC;IACrE,GAAG,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB;;;;;OAKG;IACH,GAAG,CAAC,EAAE;QACJ,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACnD,kFAAkF;QAClF,CAAC,GAAG,EAAE,OAAO,qBAAqB,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;KACpE,CAAC;IACF,oFAAoF;IACpF,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,oBAAoB,CAAC,GAAG,GAAG,OAAO;IACjD;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;IAChD;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACvC;AASD;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,sFAAsF;IACtF,QAAQ,EAAE,YAAY,CAAC;IACvB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,uFAAuF;IACvF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iEAAiE;IACjE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB;;;;;;;;;;OAUG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,0FAA0F;IAC1F,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IAMnB,0FAA0F;IAC1F,KAAK,EAAE,eAAe,CAAC;IACvB,kFAAkF;IAClF,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gEAAgE;IAChE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,4FAA4F;IAC5F,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAMzB,qDAAqD;IACrD,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED,8FAA8F;AAC9F,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,UAAU,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,UAAU,GACV,eAAe,GACf,OAAO,GACP,QAAQ,GACR,IAAI,GACJ,QAAQ,GACR,YAAY,CAAC;AAEjB;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,iDAAiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,IAAI,CACV,iBAAiB,EACjB,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,cAAc,CACzG,CAAC;CACH;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,CAAC,EAAE,oBAAoB,GAAG,iBAAiB,CA0BzE;AAwCD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,gBAAgB,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAE9E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAkGD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,aAAa,CAAC,GAAG,GAAG,OAAO,EACzC,OAAO,GAAE,oBAAoB,CAAC,GAAG,CAAM,GACtC,CAAC,CAAC,EAAE,oBAAoB,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAkC5E;AAED,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,GAAG,GAAG,OAAO;IACzC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,KAAK;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/G,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAG,OAAO,EAC7C,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,EACzB,OAAO,GAAE,oBAAoB,CAAC,GAAG,CAAM,GACtC,YAAY,CAAC,GAAG,CAAC,CA8BnB"}
|
package/dist/invocation-log.js
CHANGED
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
*/
|
|
57
57
|
// The subpath, not the root: this module is bundled into every vertical's upload (the
|
|
58
58
|
// platform entry, #1893), and the root carries every schema in the vocabulary.
|
|
59
|
-
import { encodeInvocationRecord, INVOCATION_RECORD_HEADER, invocationLevelOf, } from '@substrat-run/contracts/invocation-record';
|
|
59
|
+
import { encodeInvocationRecord, FIELD_COVERAGE_HEADER, INVOCATION_RECORD_HEADER, invocationLevelOf, } from '@substrat-run/contracts/invocation-record';
|
|
60
60
|
import { ulid } from './ulid.js';
|
|
61
|
-
import { readRoutedNode, RouterAssertionError } from './routed-node.js';
|
|
61
|
+
import { readRoutedNode, ROUTED_ID, RouterAssertionError } from './routed-node.js';
|
|
62
62
|
/**
|
|
63
63
|
* The per-request store key the middleware parks its {@link InvocationRecord} under (#1746).
|
|
64
64
|
* A published name, like `substratInvocationId`: `mountOperations` reads it in another
|
|
@@ -68,6 +68,34 @@ export const INVOCATION_RECORD_KEY = 'substratInvocationRecord';
|
|
|
68
68
|
// The level and its type moved to contracts in #1904 — the router files its datapoint under
|
|
69
69
|
// the same level — and stay exported from here, where every caller already reads them.
|
|
70
70
|
export { invocationLevelOf } from '@substrat-run/contracts/invocation-record';
|
|
71
|
+
/** Build a line. Unfilled fields are `null` (or empty), as the line's contract says. */
|
|
72
|
+
export function invocationLine(f) {
|
|
73
|
+
const emitted = f.emitted;
|
|
74
|
+
return {
|
|
75
|
+
substrat: 'invocation',
|
|
76
|
+
...(f.kind ? { kind: f.kind } : {}),
|
|
77
|
+
tenantId: f.tenantId,
|
|
78
|
+
scopeId: f.scopeId,
|
|
79
|
+
vertical: f.vertical ?? null,
|
|
80
|
+
surface: f.surface ?? null,
|
|
81
|
+
method: f.method ?? null,
|
|
82
|
+
path: f.path ?? null,
|
|
83
|
+
status: f.status ?? null,
|
|
84
|
+
threw: f.threw,
|
|
85
|
+
durationMs: f.durationMs,
|
|
86
|
+
invocationId: f.invocationId,
|
|
87
|
+
level: f.level,
|
|
88
|
+
operation: f.operation ?? null,
|
|
89
|
+
problemCode: f.problemCode ?? null,
|
|
90
|
+
principalKind: f.principalKind ?? null,
|
|
91
|
+
eventCount: emitted ? emitted.total : null,
|
|
92
|
+
eventTypes: emitted ? distinct(emitted.events.map((e) => e.type)) : [],
|
|
93
|
+
entities: emitted && f.withEntities !== false ? distinct(emitted.events.map((e) => e.entity)) : [],
|
|
94
|
+
versionId: f.versionId ?? null,
|
|
95
|
+
...(f.outputFields ? { outputFields: f.outputFields, ...(f.fieldCoverageId ? { fieldCoverageId: f.fieldCoverageId } : {}) } : {}),
|
|
96
|
+
...(f.async ?? {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
71
99
|
/** Distinct values, first occurrence wins — the order a reader expects to see them in. */
|
|
72
100
|
function distinct(values) {
|
|
73
101
|
return [...new Set(values)];
|
|
@@ -124,11 +152,49 @@ function stamps() {
|
|
|
124
152
|
export function invocationStampOf(request) {
|
|
125
153
|
return stamps().get(request);
|
|
126
154
|
}
|
|
127
|
-
|
|
155
|
+
/**
|
|
156
|
+
* #1923: whether the per-response field walk is armed for this request — the one question the
|
|
157
|
+
* walk's two callers in `vertical-host` (the operation routes and the MCP door) ask.
|
|
158
|
+
*
|
|
159
|
+
* `false` for a request no stamp covers, and for a stamp begun by a layer that predates the
|
|
160
|
+
* switch: every version skew between the platform's entry and a vertical's bundled kernel
|
|
161
|
+
* reads as off, never as on.
|
|
162
|
+
*/
|
|
163
|
+
export function fieldCoverageArmed(request) {
|
|
164
|
+
return typeof stamps().get(request)?.fieldCoverageId === 'string';
|
|
165
|
+
}
|
|
166
|
+
function beginStamp(request, env, options) {
|
|
128
167
|
const stamp = { invocationId: ulid(), record: {} };
|
|
168
|
+
const fieldCoverageId = armedFieldCoverageId(request.headers, env, options);
|
|
169
|
+
if (fieldCoverageId)
|
|
170
|
+
stamp.fieldCoverageId = fieldCoverageId;
|
|
129
171
|
stamps().set(request, stamp);
|
|
130
172
|
return stamp;
|
|
131
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* #1923: the dispatch id the ROUTER armed the field walk with for this request, or `undefined`.
|
|
176
|
+
*
|
|
177
|
+
* The header alone is a claim. It is honoured only when its value is a ULID and the request's
|
|
178
|
+
* router assertion verifies, with the same secret and the same dev opt-out as the tenant on
|
|
179
|
+
* the line, because it is trusted for the same reason: the router strips every inbound
|
|
180
|
+
* `x-substrat-*` header, and a caller that reaches the script some other way holds no secret.
|
|
181
|
+
* An unrouted request, or one whose assertion fails, is never armed.
|
|
182
|
+
*
|
|
183
|
+
* The header is read first, so a request the router did not sample — almost all of them —
|
|
184
|
+
* pays one header read and no verification.
|
|
185
|
+
*/
|
|
186
|
+
function armedFieldCoverageId(headers, env, options) {
|
|
187
|
+
let id;
|
|
188
|
+
try {
|
|
189
|
+
id = headers.get(FIELD_COVERAGE_HEADER);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
if (id === null || !ROUTED_ID.test(id))
|
|
195
|
+
return undefined;
|
|
196
|
+
return routedNodeOrNull(headers, env, options) !== null ? id : undefined;
|
|
197
|
+
}
|
|
132
198
|
/**
|
|
133
199
|
* Write the line for a finished request — the one place it is written, whichever layer
|
|
134
200
|
* started the stamp.
|
|
@@ -160,9 +226,7 @@ function writeLineOrThrow(stamp, done, options) {
|
|
|
160
226
|
if (!node)
|
|
161
227
|
return;
|
|
162
228
|
const { record, invocationId } = stamp;
|
|
163
|
-
const
|
|
164
|
-
const line = {
|
|
165
|
-
substrat: 'invocation',
|
|
229
|
+
const line = invocationLine({
|
|
166
230
|
tenantId: node.tenantId,
|
|
167
231
|
scopeId: node.scopeId,
|
|
168
232
|
vertical: node.verticalSlug,
|
|
@@ -174,15 +238,14 @@ function writeLineOrThrow(stamp, done, options) {
|
|
|
174
238
|
durationMs: Date.now() - done.started,
|
|
175
239
|
invocationId,
|
|
176
240
|
level: invocationLevelOf(done.status, done.threw, record.problemCode),
|
|
177
|
-
operation: record.operation
|
|
178
|
-
problemCode: record.problemCode
|
|
179
|
-
principalKind: record.principalKind
|
|
180
|
-
|
|
181
|
-
eventTypes: emitted ? distinct(emitted.events.map((e) => e.type)) : [],
|
|
182
|
-
entities: emitted ? distinct(emitted.events.map((e) => e.entity)) : [],
|
|
241
|
+
operation: record.operation,
|
|
242
|
+
problemCode: record.problemCode,
|
|
243
|
+
principalKind: record.principalKind,
|
|
244
|
+
...(record.emitted ? { emitted: record.emitted } : {}),
|
|
183
245
|
versionId: versionIdOf(done.env),
|
|
184
246
|
...(record.outputFields ? { outputFields: record.outputFields } : {}),
|
|
185
|
-
|
|
247
|
+
...(stamp.fieldCoverageId ? { fieldCoverageId: stamp.fieldCoverageId } : {}),
|
|
248
|
+
});
|
|
186
249
|
console.log(JSON.stringify(line));
|
|
187
250
|
}
|
|
188
251
|
/**
|
|
@@ -228,7 +291,7 @@ export function invocationLog(options = {}) {
|
|
|
228
291
|
const started = Date.now();
|
|
229
292
|
// Minted per request, before anything can emit. A ULID so it sorts by time like
|
|
230
293
|
// every other id on the spine.
|
|
231
|
-
const stamp = beginStamp(c.req.raw);
|
|
294
|
+
const stamp = beginStamp(c.req.raw, c.env, options);
|
|
232
295
|
c.set?.('substratInvocationId', stamp.invocationId);
|
|
233
296
|
c.set?.(INVOCATION_RECORD_KEY, stamp.record);
|
|
234
297
|
let threw = false;
|
|
@@ -274,7 +337,7 @@ export function withInvocationLog(worker, options = {}) {
|
|
|
274
337
|
if (invocationStampOf(request))
|
|
275
338
|
return inner.call(worker, request, env, ctx);
|
|
276
339
|
const started = Date.now();
|
|
277
|
-
const stamp = beginStamp(request);
|
|
340
|
+
const stamp = beginStamp(request, env, options);
|
|
278
341
|
let status = null;
|
|
279
342
|
let threw = false;
|
|
280
343
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invocation-log.js","sourceRoot":"","sources":["../src/invocation-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,sFAAsF;AACtF,+EAA+E;AAC/E,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,iBAAiB,GAElB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"invocation-log.js","sourceRoot":"","sources":["../src/invocation-log.ts"],"names":[],"mappings":"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"}
|
package/dist/job-run.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ import { type ExecutorRetryPolicy, type ScopeStub } from './scope-host.js';
|
|
|
94
94
|
* and the hosted store the same shape rather than merely the same intention.
|
|
95
95
|
* Spine — kernel-written, `_substrat_*`, never a module migration.
|
|
96
96
|
*/
|
|
97
|
-
export declare const JOB_RUN_DDL = "\n CREATE TABLE IF NOT EXISTS _substrat_job_runs (\n id TEXT PRIMARY KEY,\n -- The coalescing key: one LIVE run per (module_id, job, instance). Not a UNIQUE\n -- index, deliberately -- see this file's header. instance names WHAT is being\n -- walked (a source id, a mapping version); a job with one walk per scope uses\n -- the 'default' the input schema fills in.\n module_id TEXT NOT NULL,\n job TEXT NOT NULL,\n instance TEXT NOT NULL,\n -- What start() was handed, as JSON. Held to the queue-safety rule\n -- (assertQueueSafe): ids and configuration, never bytes, class instances or\n -- functions, because this value has to survive a queue message unchanged.\n payload TEXT NOT NULL,\n -- Declared subject for erasing external output without guessing from its text.\n subject_id TEXT,\n -- 'running' | 'done' | 'failed'. A killed run stays 'running' and is picked up\n -- again by the next drive -- which is exactly what makes it restartable.\n status TEXT NOT NULL,\n -- What the last COMMITTED pass handed forward, as JSON. NULL = no pass has\n -- committed yet, which is a fact ('start from the beginning'), not missing data.\n cursor TEXT,\n -- The run's counter bag (JSON object of numbers), merged on each commit. An\n -- uncommitted pass's counts are discarded with the rest of the pass.\n counters TEXT NOT NULL DEFAULT '{}',\n -- CONSECUTIVE failed passes. Reset to 0 whenever a pass commits, so this reads\n -- as \"how stuck is it now\", not \"how much work has it done\".\n attempts INTEGER NOT NULL DEFAULT 0,\n -- The error the last failed pass left. Retained after the run goes 'failed' --\n -- the record is the evidence, so it must still say why.\n last_error TEXT,\n started_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n -- When the next pass may run, on the executor's own backoff curve. NULL = now\n -- (or terminal), which is why the due read tests IS NULL as well as <= now.\n next_attempt_at TEXT,\n -- When the run reached 'done' or 'failed'. NULL while it is still running.\n ended_at TEXT\n );\n -- The drive's read: WHERE status = 'running' AND (next_attempt_at IS NULL OR <= ?)\n -- ORDER BY id. Leading with status makes the live runs a seekable range over a\n -- table that RETAINS every finished run, so the cost tracks how much is in flight\n -- rather than how much the scope has ever imported.\n CREATE INDEX IF NOT EXISTS _substrat_job_runs_due ON _substrat_job_runs (status, next_attempt_at, id);\n -- Coalescing's read, and the operator read's filter.\n CREATE INDEX IF NOT EXISTS _substrat_job_runs_key ON _substrat_job_runs (module_id, job, instance, id);\n -- The step ledger of the pass currently in flight. Rows are written as each step\n -- COMPLETES and dropped when the pass COMMITS, so this holds one pass's worth of\n -- steps and never grows with the length of the walk.\n --\n -- A FAILED run keeps its last pass's rows, deliberately: they are the difference\n -- between \"it got nowhere\" and \"it got three quarters of the way and then the\n -- provider went down\", which the run row's single last_error cannot say. Still\n -- bounded -- one pass's worth per failed run -- because a restart is a NEW run\n -- with a new id and therefore its own ledger.\n CREATE TABLE IF NOT EXISTS _substrat_job_steps (\n run_id TEXT NOT NULL,\n step TEXT NOT NULL,\n -- The step's return value as JSON. NOT NULL is what MEANS completed: a step that\n -- threw leaves the row with a NULL result and a raised attempts count, so the\n -- next pass runs it again rather than reading a success that never happened. A\n -- step returning nothing stores the JSON text 'null', which is not SQL NULL.\n result TEXT,\n attempts INTEGER NOT NULL DEFAULT 0,\n last_error TEXT,\n recorded_at TEXT NOT NULL,\n PRIMARY KEY (run_id, step)\n );\n";
|
|
97
|
+
export declare const JOB_RUN_DDL = "\n CREATE TABLE IF NOT EXISTS _substrat_job_runs (\n id TEXT PRIMARY KEY,\n -- The coalescing key: one LIVE run per (module_id, job, instance). Not a UNIQUE\n -- index, deliberately -- see this file's header. instance names WHAT is being\n -- walked (a source id, a mapping version); a job with one walk per scope uses\n -- the 'default' the input schema fills in.\n module_id TEXT NOT NULL,\n job TEXT NOT NULL,\n instance TEXT NOT NULL,\n -- What start() was handed, as JSON. Held to the queue-safety rule\n -- (assertQueueSafe): ids and configuration, never bytes, class instances or\n -- functions, because this value has to survive a queue message unchanged.\n payload TEXT NOT NULL,\n -- Declared subject for erasing external output without guessing from its text.\n subject_id TEXT,\n -- 'running' | 'done' | 'failed'. A killed run stays 'running' and is picked up\n -- again by the next drive -- which is exactly what makes it restartable.\n status TEXT NOT NULL,\n -- What the last COMMITTED pass handed forward, as JSON. NULL = no pass has\n -- committed yet, which is a fact ('start from the beginning'), not missing data.\n cursor TEXT,\n -- The run's counter bag (JSON object of numbers), merged on each commit. An\n -- uncommitted pass's counts are discarded with the rest of the pass.\n counters TEXT NOT NULL DEFAULT '{}',\n -- CONSECUTIVE failed passes. Reset to 0 whenever a pass commits, so this reads\n -- as \"how stuck is it now\", not \"how much work has it done\".\n attempts INTEGER NOT NULL DEFAULT 0,\n -- The error the last failed pass left. Retained after the run goes 'failed' --\n -- the record is the evidence, so it must still say why.\n last_error TEXT,\n started_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n -- When the next pass may run, on the executor's own backoff curve. NULL = now\n -- (or terminal), which is why the due read tests IS NULL as well as <= now.\n next_attempt_at TEXT,\n -- When the run reached 'done' or 'failed'. NULL while it is still running.\n ended_at TEXT\n );\n -- The drive's read: WHERE status = 'running' AND (next_attempt_at IS NULL OR <= ?)\n -- ORDER BY id. Leading with status makes the live runs a seekable range over a\n -- table that RETAINS every finished run, so the cost tracks how much is in flight\n -- rather than how much the scope has ever imported.\n CREATE INDEX IF NOT EXISTS _substrat_job_runs_due ON _substrat_job_runs (status, next_attempt_at, id);\n -- #1834: the drive's ORDER -- by when each run became due (JOB_RUN_DUE_AT), then id -- so a run\n -- that waited (a deferral, a backoff) queues behind work that was due before it, instead of\n -- heading every drive by its age. The expression is spelled exactly as the query spells it.\n CREATE INDEX IF NOT EXISTS _substrat_job_runs_due_at ON _substrat_job_runs (status, COALESCE(next_attempt_at, started_at), id);\n -- Coalescing's read, and the operator read's filter.\n CREATE INDEX IF NOT EXISTS _substrat_job_runs_key ON _substrat_job_runs (module_id, job, instance, id);\n -- The step ledger of the pass currently in flight. Rows are written as each step\n -- COMPLETES and dropped when the pass COMMITS, so this holds one pass's worth of\n -- steps and never grows with the length of the walk.\n --\n -- A FAILED run keeps its last pass's rows, deliberately: they are the difference\n -- between \"it got nowhere\" and \"it got three quarters of the way and then the\n -- provider went down\", which the run row's single last_error cannot say. Still\n -- bounded -- one pass's worth per failed run -- because a restart is a NEW run\n -- with a new id and therefore its own ledger.\n CREATE TABLE IF NOT EXISTS _substrat_job_steps (\n run_id TEXT NOT NULL,\n step TEXT NOT NULL,\n -- The step's return value as JSON. NOT NULL is what MEANS completed: a step that\n -- threw leaves the row with a NULL result and a raised attempts count, so the\n -- next pass runs it again rather than reading a success that never happened. A\n -- step returning nothing stores the JSON text 'null', which is not SQL NULL.\n result TEXT,\n attempts INTEGER NOT NULL DEFAULT 0,\n last_error TEXT,\n recorded_at TEXT NOT NULL,\n PRIMARY KEY (run_id, step)\n );\n";
|
|
98
98
|
/**
|
|
99
99
|
* The write every pass outcome lands through, on both adapters — a compare-and-set on
|
|
100
100
|
* `status = 'running'` (#1632).
|
|
@@ -294,6 +294,12 @@ export interface JobDriveReport {
|
|
|
294
294
|
retrying: number;
|
|
295
295
|
/** Runs whose step exhausted its retries this call. Terminal: `failed`, with the error on the record. */
|
|
296
296
|
failed: number;
|
|
297
|
+
/**
|
|
298
|
+
* Runs whose pass the host's system door told to wait (#1834): no attempt was counted and no error
|
|
299
|
+
* recorded, as a switched-off schedule is `skipped` without its cadence moving. The run is due
|
|
300
|
+
* again after `JOB_DEFER_MS`, so a run that keeps waiting never takes the turn of one behind it.
|
|
301
|
+
*/
|
|
302
|
+
deferred: number;
|
|
297
303
|
/** Per-run failures, the same shape `ScheduleRunReport.errors` has: what failed and why. */
|
|
298
304
|
errors: {
|
|
299
305
|
runId: string;
|
|
@@ -319,6 +325,12 @@ export interface JobRunRow {
|
|
|
319
325
|
readonly next_attempt_at: string | null;
|
|
320
326
|
readonly ended_at: string | null;
|
|
321
327
|
}
|
|
328
|
+
/** #1834: what a drive's snapshot holds of one due run — enough to pick it, never to act on it. */
|
|
329
|
+
export interface JobDueKey {
|
|
330
|
+
readonly id: string;
|
|
331
|
+
readonly module_id: string;
|
|
332
|
+
readonly job: string;
|
|
333
|
+
}
|
|
322
334
|
/** The `_substrat_job_steps` row, as both adapters' SQL returns it. */
|
|
323
335
|
export interface JobStepRow {
|
|
324
336
|
readonly step: string;
|
|
@@ -372,15 +384,17 @@ export interface JobRunStore {
|
|
|
372
384
|
/** One run by id, whatever its status. */
|
|
373
385
|
get(id: string): Promise<JobRunRow | null>;
|
|
374
386
|
/**
|
|
375
|
-
* `running` runs whose `next_attempt_at` has passed
|
|
376
|
-
*
|
|
387
|
+
* #1834: ONE snapshot of the keys of up to `max` `running` runs whose `next_attempt_at` has passed
|
|
388
|
+
* (or is NULL), in the order they became due (`JOB_RUN_DUE_AT`, then id), read in ONE query.
|
|
377
389
|
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
390
|
+
* Keys, not rows: the driver re-reads each row (`get`) just before it runs it, so what it acts on
|
|
391
|
+
* is never older than that re-read. The re-read RESERVES nothing: two drives overlapping on one
|
|
392
|
+
* scope can both re-read a row as due and both run it, which is why one driver per scope at a time
|
|
393
|
+
* stays a stated bound (see the file header). And one read, not pages: a cursor across separate
|
|
394
|
+
* reads met rows
|
|
395
|
+
* that a concurrent drive moved in between, and a drive then saw a run twice, or never.
|
|
382
396
|
*/
|
|
383
|
-
|
|
397
|
+
dueKeys(now: string, max: number): Promise<JobDueKey[]>;
|
|
384
398
|
list(filter: JobRunFilter): Promise<JobRunRow[]>;
|
|
385
399
|
patch(id: string, patch: JobRunPatch): Promise<void>;
|
|
386
400
|
/**
|
|
@@ -401,6 +415,27 @@ export interface JobRunStore {
|
|
|
401
415
|
}
|
|
402
416
|
/** `conflict` reason: two `step()` calls under one name in one pass. */
|
|
403
417
|
export declare const JOB_STEP_REUSED = "job_step_reused";
|
|
418
|
+
/**
|
|
419
|
+
* #1834: the reason a host's system door gives a refusal that means "not now", never "no": the
|
|
420
|
+
* module is held off on this scope until its switch is applied again, or the scope kept restarting
|
|
421
|
+
* under the door. It is for a caller READING the refusal. It decides nothing: anyone can throw an
|
|
422
|
+
* error with this reason, so the job driver never defers on it (`deferral` below is how a host
|
|
423
|
+
* says which refusals are its own).
|
|
424
|
+
*/
|
|
425
|
+
export declare const SYSTEM_DOOR_WAIT = "system_door_wait";
|
|
426
|
+
/**
|
|
427
|
+
* #1834: when a run became due — its `next_attempt_at`, or when it started if it has none — and the
|
|
428
|
+
* key the drive orders by. Ordering by id instead let an older run that keeps waiting (a deferral, a
|
|
429
|
+
* backoff) head every drive the moment it was due again, and take the turn of a run that had been
|
|
430
|
+
* due for longer. Spelled exactly as the `_substrat_job_runs_due_at` index spells it.
|
|
431
|
+
*/
|
|
432
|
+
export declare const JOB_RUN_DUE_AT = "COALESCE(next_attempt_at, started_at)";
|
|
433
|
+
/**
|
|
434
|
+
* #1834: how long a deferred run waits before it is due again. Not an attempt: nothing counts and
|
|
435
|
+
* there is no backoff. It only stops a waiting run from heading the due order on every drive, where
|
|
436
|
+
* it would take the turn of a run behind it that could make progress.
|
|
437
|
+
*/
|
|
438
|
+
export declare const JOB_DEFER_MS = 60000;
|
|
404
439
|
/**
|
|
405
440
|
* Refuse anything that cannot survive a queue message, naming the path.
|
|
406
441
|
*
|
|
@@ -457,8 +492,11 @@ export declare function jobRunOf(row: JobRunRow): JobRun;
|
|
|
457
492
|
export declare function startJobRun(store: JobRunStore, input: StartJobRunInput, mintId: () => string, now: () => string): Promise<JobRunRow>;
|
|
458
493
|
/** What one pass did, as the drive loop reads it. */
|
|
459
494
|
export interface JobPassOutcome {
|
|
460
|
-
status: 'advanced' | 'completed' | 'retrying' | 'failed';
|
|
461
|
-
/**
|
|
495
|
+
status: 'advanced' | 'completed' | 'retrying' | 'failed' | 'deferred';
|
|
496
|
+
/**
|
|
497
|
+
* The error left on the record. Present exactly on `retrying` and `failed`, and on `deferred`,
|
|
498
|
+
* where it is the door's refusal and NOT on the record: a deferred pass records no error.
|
|
499
|
+
*/
|
|
462
500
|
error?: string;
|
|
463
501
|
}
|
|
464
502
|
/**
|
|
@@ -485,8 +523,19 @@ export declare function runJobPass(options: {
|
|
|
485
523
|
/** The job's own retry policy — a step may narrow it, none may widen past its own. */
|
|
486
524
|
retry?: ExecutorRetryPolicy;
|
|
487
525
|
now: () => string;
|
|
488
|
-
/**
|
|
489
|
-
|
|
526
|
+
/**
|
|
527
|
+
* Opens the system door for this run's module. Called at most once per pass, with this pass's
|
|
528
|
+
* token: a fresh object per pass, which the host ties its door's refusals to.
|
|
529
|
+
*/
|
|
530
|
+
openScope: (pass: object) => Promise<ScopeStub>;
|
|
531
|
+
/**
|
|
532
|
+
* #1834: did the host's own system door, on THIS pass (`pass`, the token `openScope` was handed),
|
|
533
|
+
* throw this value to say "not now"? The HOST answers, by the identity of what its door threw for
|
|
534
|
+
* this pass, never by an error's shape: a step or an operation can throw any public shape, and a
|
|
535
|
+
* pass that could defer itself would wait forever without spending a retry. The host consumes
|
|
536
|
+
* the mark as it answers yes. Absent: nothing defers.
|
|
537
|
+
*/
|
|
538
|
+
deferral?: (err: unknown, pass: object) => boolean;
|
|
490
539
|
}): Promise<JobPassOutcome>;
|
|
491
540
|
/**
|
|
492
541
|
* Advance every due run on one scope — the driver both adapters expose as
|
|
@@ -503,9 +552,20 @@ export declare function runJobPass(options: {
|
|
|
503
552
|
* when the budget was applied to the query instead, a scope holding `limit` such rows
|
|
504
553
|
* at the head of the due order returned the same unrunnable batch on every call —
|
|
505
554
|
* nothing newer was ever reached, and the report said `attempted: 0` forever with no
|
|
506
|
-
* indication why. So the read
|
|
555
|
+
* indication why. So the read looks past them, bounded by `JOB_DRIVE_SCAN_MAX` rows
|
|
507
556
|
* examined so one scope full of orphans cannot turn a tick into a table scan.
|
|
508
557
|
*
|
|
558
|
+
* **Selection is ONE snapshot per drive** (#1834). The drive reads the keys of up to
|
|
559
|
+
* `JOB_DRIVE_SCAN_MAX` due runs in a single query, picks up to `limit` runnable ones
|
|
560
|
+
* (each id once), and re-reads each row just before it runs it, skipping one that is no
|
|
561
|
+
* longer `running` or no longer due. A cursor across several reads met rows that another
|
|
562
|
+
* writer had moved in between, and ran one twice or skipped it. A run that moves, or
|
|
563
|
+
* becomes due, after the snapshot is the NEXT drive's business, never this one's.
|
|
564
|
+
*
|
|
565
|
+
* The re-read is a READ, not a reservation: it does not make overlapping drives safe. Two
|
|
566
|
+
* drives on one scope at once can both re-read a row as due and both run its handler. The
|
|
567
|
+
* one-driver-per-scope bound in the file header still applies.
|
|
568
|
+
*
|
|
509
569
|
* The starvation was spotted while re-reading this file, judged unlikely and left
|
|
510
570
|
* alone — and then found independently by a reviewer. The judgement may even have
|
|
511
571
|
* been right; recording it only in the author's head was not, because a decision
|
|
@@ -515,12 +575,14 @@ export declare function runJobPass(options: {
|
|
|
515
575
|
export declare function runDueJobRuns(options: {
|
|
516
576
|
store: JobRunStore;
|
|
517
577
|
/** job name → its handler and policy, as `registerJob` recorded them. */
|
|
518
|
-
handlerFor: (run: JobRunRow) => {
|
|
578
|
+
handlerFor: (run: Pick<JobRunRow, 'module_id' | 'job'>) => {
|
|
519
579
|
handler: JobHandler;
|
|
520
580
|
retry?: ExecutorRetryPolicy;
|
|
521
581
|
} | undefined;
|
|
522
582
|
now: () => string;
|
|
523
|
-
openScope: (run: JobRunRow) => Promise<ScopeStub>;
|
|
583
|
+
openScope: (run: JobRunRow, pass: object) => Promise<ScopeStub>;
|
|
584
|
+
/** #1834: the host's own system-door refusals on one pass, by identity (`runJobPass`). */
|
|
585
|
+
deferral?: (err: unknown, pass: object) => boolean;
|
|
524
586
|
maxPasses?: number;
|
|
525
587
|
limit?: number;
|
|
526
588
|
}): Promise<JobDriveReport>;
|
package/dist/job-run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-run.d.ts","sourceRoot":"","sources":["../src/job-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC1G,OAAO,EAAiD,KAAK,mBAAmB,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE1H;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"job-run.d.ts","sourceRoot":"","sources":["../src/job-run.ts"],"names":[],"mappings":"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"}
|