@telorun/sdk 0.65.0 → 0.67.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/cancellation.d.ts +27 -0
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/cancellation.js +11 -0
- package/dist/resource-context.d.ts +63 -2
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-instance.d.ts +20 -0
- package/dist/resource-instance.d.ts.map +1 -1
- package/dist/resource-instance.js +1 -0
- package/package.json +1 -1
- package/src/cancellation.ts +31 -0
- package/src/resource-context.ts +77 -2
- package/src/resource-instance.ts +21 -0
package/dist/cancellation.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ResourceHandle } from "./resource-instance.js";
|
|
1
2
|
/**
|
|
2
3
|
* Cooperative invocation cancellation — the standard source/token split.
|
|
3
4
|
*
|
|
@@ -29,6 +30,21 @@ export interface CancellationToken {
|
|
|
29
30
|
/** Throw `ERR_INVOKE_CANCELLED` if cancelled; otherwise no-op. */
|
|
30
31
|
throwIfCancelled(): void;
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* One open execution zone — see `kernel/specs/execution-zones.md`. Three
|
|
35
|
+
* identities and nothing else: no provider-private payload rides here (a
|
|
36
|
+
* provider keys its own map on the entry), so the contract stays serializable
|
|
37
|
+
* across the ABI and another module's open transaction is never readable from
|
|
38
|
+
* the ambient stack.
|
|
39
|
+
*/
|
|
40
|
+
export interface ZoneEntry {
|
|
41
|
+
/** Canonical `<module>.<Kind>` of the providing kind — what a requirement names. */
|
|
42
|
+
readonly kind: string;
|
|
43
|
+
readonly provider: ResourceHandle;
|
|
44
|
+
/** The instance the provider's correlation-key pointer resolved to.
|
|
45
|
+
* Absent = uncorrelated zone. */
|
|
46
|
+
readonly key?: ResourceHandle;
|
|
47
|
+
}
|
|
32
48
|
/**
|
|
33
49
|
* The out-of-band second argument every `invoke()` receives. Intentionally an
|
|
34
50
|
* extensible object rather than a bare token so future per-invoke concerns
|
|
@@ -48,7 +64,18 @@ export interface InvokeContext {
|
|
|
48
64
|
* trace the way OpenTelemetry's `trace_id` does (an exporter maps it directly),
|
|
49
65
|
* independent of the parent chain. */
|
|
50
66
|
readonly traceId?: string;
|
|
67
|
+
/** Zones open around this invocation, outermost first. Absent = none. */
|
|
68
|
+
readonly zones?: readonly ZoneEntry[];
|
|
51
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* The ONE way to build a context derived from another. A fresh object literal
|
|
72
|
+
* at a rebuild site silently drops every field it does not restate — with
|
|
73
|
+
* `zones` that means the stack survives with tracing off and vanishes under
|
|
74
|
+
* `--debug`, a safety property flipping on a debug flag. Every context-rebuild
|
|
75
|
+
* site (the kernel's tracing branches, span derivation) goes through here so a
|
|
76
|
+
* field added to {@link InvokeContext} propagates without each site opting in.
|
|
77
|
+
*/
|
|
78
|
+
export declare function deriveContext(base: InvokeContext, overrides: Partial<InvokeContext>): InvokeContext;
|
|
52
79
|
/** Terminal status of a span — maps to OpenTelemetry span status. */
|
|
53
80
|
export type SpanOutcome = "ok" | "failed" | "rejected" | "cancelled";
|
|
54
81
|
/** Options for {@link ResourceContext.openSpan}. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cancellation.d.ts","sourceRoot":"","sources":["../src/cancellation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cancellation.d.ts","sourceRoot":"","sources":["../src/cancellation.ts"],"names":[],"mappings":"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"}
|
package/dist/cancellation.js
CHANGED
|
@@ -16,6 +16,17 @@ import { InvokeError } from "./invoke-error.js";
|
|
|
16
16
|
* is the primitive; `cancelAfter(ms)` is sugar over it.
|
|
17
17
|
*/
|
|
18
18
|
export const ERR_INVOKE_CANCELLED = "ERR_INVOKE_CANCELLED";
|
|
19
|
+
/**
|
|
20
|
+
* The ONE way to build a context derived from another. A fresh object literal
|
|
21
|
+
* at a rebuild site silently drops every field it does not restate — with
|
|
22
|
+
* `zones` that means the stack survives with tracing off and vanishes under
|
|
23
|
+
* `--debug`, a safety property flipping on a debug flag. Every context-rebuild
|
|
24
|
+
* site (the kernel's tracing branches, span derivation) goes through here so a
|
|
25
|
+
* field added to {@link InvokeContext} propagates without each site opting in.
|
|
26
|
+
*/
|
|
27
|
+
export function deriveContext(base, overrides) {
|
|
28
|
+
return { ...base, ...overrides };
|
|
29
|
+
}
|
|
19
30
|
class CancellationTokenSource {
|
|
20
31
|
#controller = new AbortController();
|
|
21
32
|
#cancelled = false;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CancellationSource, InvokeContext, OpenSpan, OpenSpanOptions } from "./cancellation.js";
|
|
1
|
+
import type { CancellationSource, InvokeContext, OpenSpan, OpenSpanOptions, ZoneEntry } from "./cancellation.js";
|
|
2
|
+
import type { ResourceHandle } from "./resource-instance.js";
|
|
2
3
|
import { ControllerContext } from "./controller-context.js";
|
|
3
4
|
import type { Logger } from "./logger.js";
|
|
4
5
|
import type { LoggingHost } from "./log-sink.js";
|
|
@@ -36,6 +37,20 @@ export declare class NoopValidator implements DataValidator {
|
|
|
36
37
|
export type ParsedArgs = Partial<Record<string, string | boolean | string[]>> & {
|
|
37
38
|
_: string[];
|
|
38
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Per-call options for a by-name dispatch.
|
|
42
|
+
*
|
|
43
|
+
* A bag rather than a positional context parameter because this slot already
|
|
44
|
+
* carried one meaning — `retry`, consumed by the step leaf — and
|
|
45
|
+
* `ResourceContext` satisfies `InvokeStepContext` structurally, so a positional
|
|
46
|
+
* `InvokeContext` here silently receives a step's retry options instead.
|
|
47
|
+
*/
|
|
48
|
+
export interface InvokeByNameOptions {
|
|
49
|
+
/** Seeds the invocation context, replacing the ambient. */
|
|
50
|
+
ctx?: InvokeContext;
|
|
51
|
+
/** Retry policy, read by `executeInvokeStep`. */
|
|
52
|
+
retry?: unknown;
|
|
53
|
+
}
|
|
39
54
|
export interface ResourceContext extends ControllerContext {
|
|
40
55
|
readonly args: ParsedArgs;
|
|
41
56
|
/** The id prefix of the context this resource was created in (the creating
|
|
@@ -72,6 +87,48 @@ export interface ResourceContext extends ControllerContext {
|
|
|
72
87
|
* lambda budget). Pass `source.context` into `invokeResolved` to scope an
|
|
73
88
|
* invocation tree to it. */
|
|
74
89
|
createCancellationSource(): CancellationSource;
|
|
90
|
+
/** This resource's own handle. Its `ref` is how a controller names itself in a
|
|
91
|
+
* diagnostic; its id is what the kernel stamps as a zone's `provider`. */
|
|
92
|
+
readonly self: ResourceHandle;
|
|
93
|
+
/**
|
|
94
|
+
* Open the zone declared by this resource's `slot` (`x-telo-provides-zone`)
|
|
95
|
+
* around `fn`. Kind = the declaring kind; correlation key = the annotation's
|
|
96
|
+
* pointer, resolved against this resource's own manifest. Throws if `slot`
|
|
97
|
+
* carries no such annotation — a controller and its schema disagreeing is a
|
|
98
|
+
* defect, not a fallback.
|
|
99
|
+
*
|
|
100
|
+
* A scope function rather than a push/pop pair: push/pop cannot be honest
|
|
101
|
+
* across async boundaries. `fn` receives the derived context to thread into
|
|
102
|
+
* `invokeResolved` for the body — the discipline cancellation already has —
|
|
103
|
+
* and the minted entry, which a provider with private state (an open
|
|
104
|
+
* transaction, a journal) keys its own map on.
|
|
105
|
+
*
|
|
106
|
+
* `base` is the context the new zone is layered onto. Pass the
|
|
107
|
+
* {@link InvokeContext} the controller was handed, exactly as
|
|
108
|
+
* {@link requireZone} takes one: a runtime with no ambient store (the Rust
|
|
109
|
+
* kernel passes its context explicitly and has none) can only implement the
|
|
110
|
+
* provider half through this parameter, so omitting it would make the surface
|
|
111
|
+
* unportable. Defaults to the ambient context.
|
|
112
|
+
*/
|
|
113
|
+
withZone<T>(slot: string, fn: (ctx: InvokeContext, entry: ZoneEntry) => Promise<T>, base?: InvokeContext): Promise<T>;
|
|
114
|
+
/** The zone required by this resource's `field` (`x-telo-requires-zone`), or
|
|
115
|
+
* throw ERR_ZONE_REQUIRED. Reads the ambient stack unless `ctx` is given. */
|
|
116
|
+
requireZone(field: string, ctx?: InvokeContext): ZoneEntry;
|
|
117
|
+
/** Like {@link requireZone} but absence is a valid answer, not an error. */
|
|
118
|
+
findZone(field: string, ctx?: InvokeContext): ZoneEntry | undefined;
|
|
119
|
+
/** Ambient zones correlated on an instance the caller holds, innermost first —
|
|
120
|
+
* the undeclared case (a statement with no `transaction:` still joins an open
|
|
121
|
+
* one). No kind parameter: the provider's own per-instance map already
|
|
122
|
+
* discriminates — a zone this instance's owner did not open simply misses. */
|
|
123
|
+
zonesFor(instance: ResourceInstance, ctx?: InvokeContext): readonly ZoneEntry[];
|
|
124
|
+
/** The root context for runtime-driven inbound work (request, timer, queue
|
|
125
|
+
* message): inherits nothing from whatever ambient happens to be live at the
|
|
126
|
+
* registration site — no zones, no trace parent, no caller token. An inbound
|
|
127
|
+
* registrant dispatches with this (or a cancellation source's context, which
|
|
128
|
+
* is one), never `undefined`. */
|
|
129
|
+
rootContext(opts?: {
|
|
130
|
+
cancellation?: CancellationSource;
|
|
131
|
+
}): InvokeContext;
|
|
75
132
|
/** Run `fn` detached from the caller's cancellation/trace scope: the ambient
|
|
76
133
|
* request token + span are replaced with the uncancellable root, so request
|
|
77
134
|
* teardown cannot abort the work and it does not nest under the request's
|
|
@@ -86,7 +143,11 @@ export interface ResourceContext extends ControllerContext {
|
|
|
86
143
|
* (e.g. a W3C `traceparent`). A no-op (returns `base` unchanged) when tracing
|
|
87
144
|
* is off. */
|
|
88
145
|
openSpan(base: InvokeContext | undefined, opts: OpenSpanOptions): Promise<OpenSpan>;
|
|
89
|
-
|
|
146
|
+
/** Dispatch by name through the traced chokepoint. See
|
|
147
|
+
* {@link InvokeByNameOptions} for `ctx` — an inbound registrant passes
|
|
148
|
+
* {@link rootContext} there so the handler inherits nothing ambient
|
|
149
|
+
* (execution-zones spec §7). */
|
|
150
|
+
invoke<TInputs>(kind: string, name: string, inputs: TInputs, options?: InvokeByNameOptions): Promise<any>;
|
|
90
151
|
invokeResolved<TInputs>(kind: string, name: string, instance: ResourceInstance, inputs: TInputs, ctx?: InvokeContext): Promise<any>;
|
|
91
152
|
run(kind: string, name: string): Promise<void>;
|
|
92
153
|
getResourcesByName(kind: string, name: string): RuntimeResource | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-context.d.ts","sourceRoot":"","sources":["../src/resource-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"resource-context.d.ts","sourceRoot":"","sources":["../src/resource-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,26 @@ export interface RefIdentity {
|
|
|
29
29
|
kind: string;
|
|
30
30
|
name: string;
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Kernel-minted, unique per LIVE instance, stable for its lifetime. Distinct
|
|
34
|
+
* from {@link RefIdentity}: a `with:`-scoped resource has one declaration and
|
|
35
|
+
* one instance per scope run, and correlation must see those as different.
|
|
36
|
+
* A string rather than an object reference so it serializes across the ABI —
|
|
37
|
+
* a second-language kernel compares the same value.
|
|
38
|
+
*/
|
|
39
|
+
export type ResourceInstanceId = string & {
|
|
40
|
+
readonly __brand: "ResourceInstanceId";
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Typed identity of a live resource instance. `id` is the only thing compared;
|
|
44
|
+
* `ref` is where the instance was declared — diagnostics only, so an error can
|
|
45
|
+
* say *no transaction open on connection `appDb`* instead of printing an id.
|
|
46
|
+
*/
|
|
47
|
+
export interface ResourceHandle {
|
|
48
|
+
readonly id: ResourceInstanceId;
|
|
49
|
+
readonly ref: RefIdentity;
|
|
50
|
+
}
|
|
51
|
+
export declare const sameResource: (a: ResourceHandle, b: ResourceHandle) => boolean;
|
|
32
52
|
/**
|
|
33
53
|
* Non-enumerable identity tag the kernel stamps on a live instance when it
|
|
34
54
|
* injects a resolved `!ref` into a slot. A consumer that holds only the bare
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-instance.d.ts","sourceRoot":"","sources":["../src/resource-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CACjF,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAC3B,GACC,OAAO,CAAC,QAAQ,CAAC,GACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG;IAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEJ;;mBAEmB;AACnB,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,MAAuC,CAAC;AAE1E;sFACsF;AACtF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CASnF;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExE"}
|
|
1
|
+
{"version":3,"file":"resource-instance.d.ts","sourceRoot":"","sources":["../src/resource-instance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,MAAM,gBAAgB,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CACjF,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAC3B,GACC,OAAO,CAAC,QAAQ,CAAC,GACjB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG;IAC3B,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,QAAQ,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEJ;;mBAEmB;AACnB,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAErF;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,kBAAkB,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;CAC3B;AAED,eAAO,MAAM,YAAY,GAAI,GAAG,cAAc,EAAE,GAAG,cAAc,KAAG,OAAwB,CAAC;AAE7F;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,MAAuC,CAAC;AAE1E;sFACsF;AACtF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CASnF;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExE"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* sinks use it so anything logging during its own teardown still reaches a live
|
|
3
3
|
* destination. */
|
|
4
4
|
export const TEARDOWN_LAST = 1000;
|
|
5
|
+
export const sameResource = (a, b) => a.id === b.id;
|
|
5
6
|
/**
|
|
6
7
|
* Non-enumerable identity tag the kernel stamps on a live instance when it
|
|
7
8
|
* injects a resolved `!ref` into a slot. A consumer that holds only the bare
|
package/package.json
CHANGED
package/src/cancellation.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InvokeError } from "./invoke-error.js";
|
|
2
|
+
import type { ResourceHandle } from "./resource-instance.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Cooperative invocation cancellation — the standard source/token split.
|
|
@@ -34,6 +35,22 @@ export interface CancellationToken {
|
|
|
34
35
|
throwIfCancelled(): void;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
* One open execution zone — see `kernel/specs/execution-zones.md`. Three
|
|
40
|
+
* identities and nothing else: no provider-private payload rides here (a
|
|
41
|
+
* provider keys its own map on the entry), so the contract stays serializable
|
|
42
|
+
* across the ABI and another module's open transaction is never readable from
|
|
43
|
+
* the ambient stack.
|
|
44
|
+
*/
|
|
45
|
+
export interface ZoneEntry {
|
|
46
|
+
/** Canonical `<module>.<Kind>` of the providing kind — what a requirement names. */
|
|
47
|
+
readonly kind: string;
|
|
48
|
+
readonly provider: ResourceHandle;
|
|
49
|
+
/** The instance the provider's correlation-key pointer resolved to.
|
|
50
|
+
* Absent = uncorrelated zone. */
|
|
51
|
+
readonly key?: ResourceHandle;
|
|
52
|
+
}
|
|
53
|
+
|
|
37
54
|
/**
|
|
38
55
|
* The out-of-band second argument every `invoke()` receives. Intentionally an
|
|
39
56
|
* extensible object rather than a bare token so future per-invoke concerns
|
|
@@ -53,6 +70,20 @@ export interface InvokeContext {
|
|
|
53
70
|
* trace the way OpenTelemetry's `trace_id` does (an exporter maps it directly),
|
|
54
71
|
* independent of the parent chain. */
|
|
55
72
|
readonly traceId?: string;
|
|
73
|
+
/** Zones open around this invocation, outermost first. Absent = none. */
|
|
74
|
+
readonly zones?: readonly ZoneEntry[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The ONE way to build a context derived from another. A fresh object literal
|
|
79
|
+
* at a rebuild site silently drops every field it does not restate — with
|
|
80
|
+
* `zones` that means the stack survives with tracing off and vanishes under
|
|
81
|
+
* `--debug`, a safety property flipping on a debug flag. Every context-rebuild
|
|
82
|
+
* site (the kernel's tracing branches, span derivation) goes through here so a
|
|
83
|
+
* field added to {@link InvokeContext} propagates without each site opting in.
|
|
84
|
+
*/
|
|
85
|
+
export function deriveContext(base: InvokeContext, overrides: Partial<InvokeContext>): InvokeContext {
|
|
86
|
+
return { ...base, ...overrides };
|
|
56
87
|
}
|
|
57
88
|
|
|
58
89
|
/** Terminal status of a span — maps to OpenTelemetry span status. */
|
package/src/resource-context.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
CancellationSource,
|
|
3
|
+
InvokeContext,
|
|
4
|
+
OpenSpan,
|
|
5
|
+
OpenSpanOptions,
|
|
6
|
+
ZoneEntry,
|
|
7
|
+
} from "./cancellation.js";
|
|
8
|
+
import type { ResourceHandle } from "./resource-instance.js";
|
|
2
9
|
import { ControllerContext } from "./controller-context.js";
|
|
3
10
|
import type { Logger } from "./logger.js";
|
|
4
11
|
import type { LoggingHost } from "./log-sink.js";
|
|
@@ -45,6 +52,21 @@ export class NoopValidator implements DataValidator {
|
|
|
45
52
|
|
|
46
53
|
export type ParsedArgs = Partial<Record<string, string | boolean | string[]>> & { _: string[] };
|
|
47
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Per-call options for a by-name dispatch.
|
|
57
|
+
*
|
|
58
|
+
* A bag rather than a positional context parameter because this slot already
|
|
59
|
+
* carried one meaning — `retry`, consumed by the step leaf — and
|
|
60
|
+
* `ResourceContext` satisfies `InvokeStepContext` structurally, so a positional
|
|
61
|
+
* `InvokeContext` here silently receives a step's retry options instead.
|
|
62
|
+
*/
|
|
63
|
+
export interface InvokeByNameOptions {
|
|
64
|
+
/** Seeds the invocation context, replacing the ambient. */
|
|
65
|
+
ctx?: InvokeContext;
|
|
66
|
+
/** Retry policy, read by `executeInvokeStep`. */
|
|
67
|
+
retry?: unknown;
|
|
68
|
+
}
|
|
69
|
+
|
|
48
70
|
export interface ResourceContext extends ControllerContext {
|
|
49
71
|
readonly args: ParsedArgs;
|
|
50
72
|
/** The id prefix of the context this resource was created in (the creating
|
|
@@ -81,6 +103,50 @@ export interface ResourceContext extends ControllerContext {
|
|
|
81
103
|
* lambda budget). Pass `source.context` into `invokeResolved` to scope an
|
|
82
104
|
* invocation tree to it. */
|
|
83
105
|
createCancellationSource(): CancellationSource;
|
|
106
|
+
/** This resource's own handle. Its `ref` is how a controller names itself in a
|
|
107
|
+
* diagnostic; its id is what the kernel stamps as a zone's `provider`. */
|
|
108
|
+
readonly self: ResourceHandle;
|
|
109
|
+
/**
|
|
110
|
+
* Open the zone declared by this resource's `slot` (`x-telo-provides-zone`)
|
|
111
|
+
* around `fn`. Kind = the declaring kind; correlation key = the annotation's
|
|
112
|
+
* pointer, resolved against this resource's own manifest. Throws if `slot`
|
|
113
|
+
* carries no such annotation — a controller and its schema disagreeing is a
|
|
114
|
+
* defect, not a fallback.
|
|
115
|
+
*
|
|
116
|
+
* A scope function rather than a push/pop pair: push/pop cannot be honest
|
|
117
|
+
* across async boundaries. `fn` receives the derived context to thread into
|
|
118
|
+
* `invokeResolved` for the body — the discipline cancellation already has —
|
|
119
|
+
* and the minted entry, which a provider with private state (an open
|
|
120
|
+
* transaction, a journal) keys its own map on.
|
|
121
|
+
*
|
|
122
|
+
* `base` is the context the new zone is layered onto. Pass the
|
|
123
|
+
* {@link InvokeContext} the controller was handed, exactly as
|
|
124
|
+
* {@link requireZone} takes one: a runtime with no ambient store (the Rust
|
|
125
|
+
* kernel passes its context explicitly and has none) can only implement the
|
|
126
|
+
* provider half through this parameter, so omitting it would make the surface
|
|
127
|
+
* unportable. Defaults to the ambient context.
|
|
128
|
+
*/
|
|
129
|
+
withZone<T>(
|
|
130
|
+
slot: string,
|
|
131
|
+
fn: (ctx: InvokeContext, entry: ZoneEntry) => Promise<T>,
|
|
132
|
+
base?: InvokeContext,
|
|
133
|
+
): Promise<T>;
|
|
134
|
+
/** The zone required by this resource's `field` (`x-telo-requires-zone`), or
|
|
135
|
+
* throw ERR_ZONE_REQUIRED. Reads the ambient stack unless `ctx` is given. */
|
|
136
|
+
requireZone(field: string, ctx?: InvokeContext): ZoneEntry;
|
|
137
|
+
/** Like {@link requireZone} but absence is a valid answer, not an error. */
|
|
138
|
+
findZone(field: string, ctx?: InvokeContext): ZoneEntry | undefined;
|
|
139
|
+
/** Ambient zones correlated on an instance the caller holds, innermost first —
|
|
140
|
+
* the undeclared case (a statement with no `transaction:` still joins an open
|
|
141
|
+
* one). No kind parameter: the provider's own per-instance map already
|
|
142
|
+
* discriminates — a zone this instance's owner did not open simply misses. */
|
|
143
|
+
zonesFor(instance: ResourceInstance, ctx?: InvokeContext): readonly ZoneEntry[];
|
|
144
|
+
/** The root context for runtime-driven inbound work (request, timer, queue
|
|
145
|
+
* message): inherits nothing from whatever ambient happens to be live at the
|
|
146
|
+
* registration site — no zones, no trace parent, no caller token. An inbound
|
|
147
|
+
* registrant dispatches with this (or a cancellation source's context, which
|
|
148
|
+
* is one), never `undefined`. */
|
|
149
|
+
rootContext(opts?: { cancellation?: CancellationSource }): InvokeContext;
|
|
84
150
|
/** Run `fn` detached from the caller's cancellation/trace scope: the ambient
|
|
85
151
|
* request token + span are replaced with the uncancellable root, so request
|
|
86
152
|
* teardown cannot abort the work and it does not nest under the request's
|
|
@@ -95,7 +161,16 @@ export interface ResourceContext extends ControllerContext {
|
|
|
95
161
|
* (e.g. a W3C `traceparent`). A no-op (returns `base` unchanged) when tracing
|
|
96
162
|
* is off. */
|
|
97
163
|
openSpan(base: InvokeContext | undefined, opts: OpenSpanOptions): Promise<OpenSpan>;
|
|
98
|
-
|
|
164
|
+
/** Dispatch by name through the traced chokepoint. See
|
|
165
|
+
* {@link InvokeByNameOptions} for `ctx` — an inbound registrant passes
|
|
166
|
+
* {@link rootContext} there so the handler inherits nothing ambient
|
|
167
|
+
* (execution-zones spec §7). */
|
|
168
|
+
invoke<TInputs>(
|
|
169
|
+
kind: string,
|
|
170
|
+
name: string,
|
|
171
|
+
inputs: TInputs,
|
|
172
|
+
options?: InvokeByNameOptions,
|
|
173
|
+
): Promise<any>;
|
|
99
174
|
invokeResolved<TInputs>(
|
|
100
175
|
kind: string,
|
|
101
176
|
name: string,
|
package/src/resource-instance.ts
CHANGED
|
@@ -37,6 +37,27 @@ export interface RefIdentity {
|
|
|
37
37
|
name: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Kernel-minted, unique per LIVE instance, stable for its lifetime. Distinct
|
|
42
|
+
* from {@link RefIdentity}: a `with:`-scoped resource has one declaration and
|
|
43
|
+
* one instance per scope run, and correlation must see those as different.
|
|
44
|
+
* A string rather than an object reference so it serializes across the ABI —
|
|
45
|
+
* a second-language kernel compares the same value.
|
|
46
|
+
*/
|
|
47
|
+
export type ResourceInstanceId = string & { readonly __brand: "ResourceInstanceId" };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Typed identity of a live resource instance. `id` is the only thing compared;
|
|
51
|
+
* `ref` is where the instance was declared — diagnostics only, so an error can
|
|
52
|
+
* say *no transaction open on connection `appDb`* instead of printing an id.
|
|
53
|
+
*/
|
|
54
|
+
export interface ResourceHandle {
|
|
55
|
+
readonly id: ResourceInstanceId;
|
|
56
|
+
readonly ref: RefIdentity;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const sameResource = (a: ResourceHandle, b: ResourceHandle): boolean => a.id === b.id;
|
|
60
|
+
|
|
40
61
|
/**
|
|
41
62
|
* Non-enumerable identity tag the kernel stamps on a live instance when it
|
|
42
63
|
* injects a resolved `!ref` into a slot. A consumer that holds only the bare
|