@telorun/sdk 0.77.0 → 0.80.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 +50 -1
- package/dist/cancellation.d.ts.map +1 -1
- package/dist/contract-errors.d.ts +8 -1
- package/dist/contract-errors.d.ts.map +1 -1
- package/dist/contract-errors.js +8 -0
- package/dist/durable-run.d.ts +310 -0
- package/dist/durable-run.d.ts.map +1 -0
- package/dist/durable-run.js +223 -0
- package/dist/durable-suspension.d.ts +143 -0
- package/dist/durable-suspension.d.ts.map +1 -0
- package/dist/durable-suspension.js +153 -0
- package/dist/durable-target-encoding.d.ts +49 -0
- package/dist/durable-target-encoding.d.ts.map +1 -0
- package/dist/durable-target-encoding.js +121 -0
- package/dist/duration.d.ts +1 -1
- package/dist/duration.js +5 -5
- package/dist/evaluation-context.d.ts +16 -0
- package/dist/evaluation-context.d.ts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/invoke-step.d.ts +86 -1
- package/dist/invoke-step.d.ts.map +1 -1
- package/dist/invoke-step.js +261 -18
- package/dist/resource-context.d.ts +37 -0
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-instance.d.ts +21 -1
- package/dist/resource-instance.d.ts.map +1 -1
- package/dist/resource-instance.js +6 -2
- package/dist/step-engine.d.ts +170 -0
- package/dist/step-engine.d.ts.map +1 -0
- package/dist/step-engine.js +365 -0
- package/dist/zone-attribute.d.ts +101 -0
- package/dist/zone-attribute.d.ts.map +1 -0
- package/dist/zone-attribute.js +130 -0
- package/dist/zone-attributes/entries/atomic.json +7 -0
- package/dist/zone-attributes/entries/idempotent.json +6 -0
- package/dist/zone-attributes/entries/index.d.ts +3 -0
- package/dist/zone-attributes/entries/index.d.ts.map +1 -0
- package/dist/zone-attributes/entries/index.js +13 -0
- package/dist/zone-attributes/entries/no-suspend.json +6 -0
- package/dist/zone-attributes/entries/replayed.json +6 -0
- package/package.json +1 -1
- package/src/cancellation.ts +50 -1
- package/src/contract-errors.ts +9 -0
- package/src/durable-run.ts +450 -0
- package/src/durable-suspension.ts +188 -0
- package/src/durable-target-encoding.ts +181 -0
- package/src/duration.ts +5 -5
- package/src/evaluation-context.ts +17 -0
- package/src/index.ts +5 -1
- package/src/invoke-step.ts +378 -24
- package/src/resource-context.ts +37 -0
- package/src/resource-instance.ts +32 -2
- package/src/step-engine.ts +627 -0
- package/src/zone-attribute.ts +208 -0
- package/src/zone-attributes/entries/atomic.json +7 -0
- package/src/zone-attributes/entries/idempotent.json +6 -0
- package/src/zone-attributes/entries/index.ts +14 -0
- package/src/zone-attributes/entries/no-suspend.json +6 -0
- package/src/zone-attributes/entries/replayed.json +6 -0
package/dist/invoke-step.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ERR_INVOKE_CANCELLED, isCancellationError, } from "./cancellation.js";
|
|
1
|
+
import { ERR_INVOKE_CANCELLED, UNCANCELLABLE_CONTEXT, createCancellationSource, deriveContext, isCancellationError, } from "./cancellation.js";
|
|
2
2
|
import { isAmbientContractErrorCode } from "./contract-errors.js";
|
|
3
|
+
import { durableHandleOf, journalingSuppressed, stepPath, } from "./durable-run.js";
|
|
4
|
+
import { SUSPENDING_BACKOFF_MS, assertMaySuspend, isSuspension, parkRun, } from "./durable-suspension.js";
|
|
3
5
|
import { tryParseDurationMs } from "./duration.js";
|
|
4
6
|
import { InvokeError } from "./invoke-error.js";
|
|
5
7
|
import { getRefIdentity } from "./resource-instance.js";
|
|
@@ -13,11 +15,129 @@ export async function executeInvokeStep(step, ctx, state) {
|
|
|
13
15
|
const cel = { steps: state.steps, ...state.cel };
|
|
14
16
|
if (step.when !== undefined && !ctx.expandValue(step.when, cel))
|
|
15
17
|
return;
|
|
16
|
-
const
|
|
18
|
+
const rawHandle = durableHandleOf(state.invokeCtx);
|
|
19
|
+
// Inside a collapsed region the engine records NOTHING of its own: the region
|
|
20
|
+
// re-runs whole on resume, so per-step entries would describe work that is
|
|
21
|
+
// about to happen again. A resource inside it may still journal directly —
|
|
22
|
+
// which is what lets `Durable.Value` pin an impure evaluation there rather
|
|
23
|
+
// than be a prescription with nowhere to write.
|
|
24
|
+
const handle = rawHandle && journalingSuppressed(ctx, state.invokeCtx, rawHandle) ? undefined : rawHandle;
|
|
25
|
+
const path = state.journalPath ?? step.name;
|
|
26
|
+
// The RESOLVED inputs are journaled, not re-derived. They are read from a CEL
|
|
27
|
+
// scope carrying live readings — `resources.<name>.status` is republished on
|
|
28
|
+
// every dispatch by design — so a fresh process can compute different
|
|
29
|
+
// arguments for the same step and hand them to a target the journal will then
|
|
30
|
+
// answer for, with no mismatch to detect.
|
|
31
|
+
const inputs = (handle
|
|
32
|
+
? await handle.decide(stepPath(path, "inputs"), "inputs", () => ctx.expandValue(step.inputs ?? {}, cel))
|
|
33
|
+
: ctx.expandValue(step.inputs ?? {}, cel));
|
|
17
34
|
const raw = step.invoke;
|
|
18
|
-
|
|
35
|
+
// The dispatch carries THIS step's path, so anything it reaches that runs a
|
|
36
|
+
// step body of its own hangs those paths under this one rather than starting
|
|
37
|
+
// over at the root. Set only inside a durable run: outside one there is no
|
|
38
|
+
// path to carry, and deriving a context would be a rebuild for nothing.
|
|
39
|
+
// Derived from the RAW handle, not the collapse-suppressed one: collapse
|
|
40
|
+
// suppresses the engine's own per-step entries, never the journal. A
|
|
41
|
+
// `Durable.Value` or a parking kind inside a collapsed region still records
|
|
42
|
+
// directly, and it keys off this path — so dropping it here would give every
|
|
43
|
+
// such resource in the region ONE key inherited from an enclosing level.
|
|
44
|
+
const stepCtx = rawHandle && state.invokeCtx
|
|
45
|
+
? deriveContext(state.invokeCtx, { durablePath: path })
|
|
46
|
+
: state.invokeCtx;
|
|
47
|
+
const execute = () => withStepRetry(step, stepCtx, ctx, rawHandle, path, (attemptCtx) => withStepTimeout(step, attemptCtx, (dispatchCtx) => dispatch(raw, inputs, ctx, { ...state, invokeCtx: dispatchCtx })));
|
|
48
|
+
// Retry and the timeout sit INSIDE the handed-over effect, not around it: a
|
|
49
|
+
// re-attempt is part of performing this step once, so a backend that ships the
|
|
50
|
+
// step elsewhere ships its policy with it rather than re-attempting a remote
|
|
51
|
+
// dispatch it does not own. This is also what keeps the attempt loop's own
|
|
52
|
+
// rule intact — the journal records the OUTCOME of the step, and a step whose
|
|
53
|
+
// third attempt succeeded completed once.
|
|
54
|
+
const result = handle
|
|
55
|
+
? await handle.step(path, targetIdentityOf(raw, ctx, state), inputs, execute)
|
|
56
|
+
: await execute();
|
|
19
57
|
state.steps[step.name] = { result };
|
|
20
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* The target's DECLARATION-SITE identity, for a backend that may execute the
|
|
61
|
+
* step somewhere the instance does not exist.
|
|
62
|
+
*
|
|
63
|
+
* Derived from the `!ref` identity the kernel stamps at Phase-5 injection, which
|
|
64
|
+
* is the only declaration-site fact a resolved target carries — instance
|
|
65
|
+
* identity is process-local by construction. Undefined when the step dispatches
|
|
66
|
+
* something with no stamp (a truly anonymous instance), which a local backend
|
|
67
|
+
* handles by simply running `execute` and a relocating one must refuse rather
|
|
68
|
+
* than guess.
|
|
69
|
+
*/
|
|
70
|
+
function targetIdentityOf(raw, ctx, state) {
|
|
71
|
+
if (!raw || typeof raw !== "object")
|
|
72
|
+
return undefined;
|
|
73
|
+
// A pre-injected instance carries the stamp already.
|
|
74
|
+
const behind = getRefIdentity(raw) ? undefined : instanceBehind(raw, ctx, state);
|
|
75
|
+
const stamped = getRefIdentity(raw) ?? (behind && getRefIdentity(behind.instance));
|
|
76
|
+
const ref = raw;
|
|
77
|
+
const kind = stamped?.kind ?? (typeof ref.kind === "string" ? ref.kind : undefined);
|
|
78
|
+
const name = stamped?.name ?? (typeof ref.name === "string" ? ref.name : undefined);
|
|
79
|
+
if (!kind || !name)
|
|
80
|
+
return undefined;
|
|
81
|
+
return {
|
|
82
|
+
kind,
|
|
83
|
+
name,
|
|
84
|
+
// Whether the name resolved inside a `with:` scope, which is knowable HERE
|
|
85
|
+
// and only here — the resolution is what answers it. The tuple identifying
|
|
86
|
+
// which scope RUN is not derivable yet, so this is what stops such a target
|
|
87
|
+
// being encoded as the module-level resource that shares its name.
|
|
88
|
+
...(behind?.scoped ? { scoped: true } : {}),
|
|
89
|
+
// Carried through verbatim: the kernel derived it at the declaration site,
|
|
90
|
+
// which is the only place it is knowable, and a consumer that must name this
|
|
91
|
+
// target elsewhere has nothing else to name it with.
|
|
92
|
+
...(stamped?.origin?.module === undefined ? {} : { module: stamped.origin.module }),
|
|
93
|
+
...(stamped?.origin?.pointer === undefined ? {} : { pointer: stamped.origin.pointer }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The live instance behind a step's `invoke:` REF, when this host can name one.
|
|
98
|
+
*
|
|
99
|
+
* A step's slot is not a Phase-5 injection site — it resolves at dispatch — so a
|
|
100
|
+
* step target arrives as a `{kind, name, alias?}` reference and carries no stamp
|
|
101
|
+
* of its own. Reading the instance's is what recovers the declaration site, and
|
|
102
|
+
* the resolution mirrors `dispatch`'s branches exactly so the identity describes
|
|
103
|
+
* the resource the step will actually reach.
|
|
104
|
+
*
|
|
105
|
+
* Reports whether the name resolved inside a `with:` SCOPE as well as what it
|
|
106
|
+
* resolved to, because that is a fact only the resolution knows and it changes
|
|
107
|
+
* what the identity means: a scoped name and a module-level one can be the same
|
|
108
|
+
* string and different resources.
|
|
109
|
+
*
|
|
110
|
+
* Best-effort by design: every resolver here is optional, and a host that
|
|
111
|
+
* supplies none yields an identity of kind and name alone — enough for a local
|
|
112
|
+
* backend, and refused by a relocating one rather than guessed at.
|
|
113
|
+
*/
|
|
114
|
+
function instanceBehind(raw, ctx, state) {
|
|
115
|
+
const ref = raw;
|
|
116
|
+
if (typeof ref.name !== "string")
|
|
117
|
+
return undefined;
|
|
118
|
+
try {
|
|
119
|
+
if (ref.alias && ref.alias !== "Self") {
|
|
120
|
+
const imported = ctx.resolveImportedInstance?.(ref.alias, ref.name);
|
|
121
|
+
return imported && { instance: imported, scoped: false };
|
|
122
|
+
}
|
|
123
|
+
if (state.scope) {
|
|
124
|
+
// Scope-local FIRST, enclosing module as the fallback — the order
|
|
125
|
+
// `ScopeContext.getInstance` and the CEL `resources` layering already use,
|
|
126
|
+
// so what this reports a name to mean is what the dispatch will reach.
|
|
127
|
+
const scoped = state.scope.getInstance(ref.name);
|
|
128
|
+
if (scoped)
|
|
129
|
+
return { instance: scoped, scoped: true };
|
|
130
|
+
}
|
|
131
|
+
const local = ctx.resolveLocalInstance?.(ref.name);
|
|
132
|
+
return local && { instance: local, scoped: false };
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// A resolver that throws is answering "not here", and the dispatch below is
|
|
136
|
+
// where that becomes an error with a message about the dispatch. Recovering
|
|
137
|
+
// provenance must not be the thing that reports it.
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
21
141
|
/**
|
|
22
142
|
* Re-attempt a step's dispatch while its policy allows.
|
|
23
143
|
*
|
|
@@ -48,39 +168,156 @@ export async function executeInvokeStep(step, ctx, state) {
|
|
|
48
168
|
* for a caller that assembled a policy in code rather than from a manifest — not
|
|
49
169
|
* a second, competing statement of what a default is.
|
|
50
170
|
*/
|
|
51
|
-
async function withStepRetry(step, invokeCtx, dispatch) {
|
|
171
|
+
async function withStepRetry(step, invokeCtx, ctx, handle, path, dispatch) {
|
|
52
172
|
const policy = step.retry;
|
|
53
173
|
const attempts = policy?.attempts ?? 0;
|
|
54
174
|
if (!policy || attempts <= 0)
|
|
55
|
-
return dispatch();
|
|
56
|
-
const initial = policy.initialDelay ?? parseDuration(policy.delay) ?? 250;
|
|
57
|
-
const factor = policy.factor ?? 2;
|
|
58
|
-
const maxDelay = policy.maxDelay ?? 32_000;
|
|
175
|
+
return dispatch(invokeCtx);
|
|
59
176
|
const jitter = policy.jitter ?? "full";
|
|
60
177
|
for (let resend = 0;; resend++) {
|
|
61
178
|
try {
|
|
62
|
-
return await dispatch();
|
|
179
|
+
return await dispatch(invokeCtx);
|
|
63
180
|
}
|
|
64
181
|
catch (err) {
|
|
65
|
-
if (resend >= attempts || !isRetryable(err))
|
|
182
|
+
if (resend >= attempts || !isRetryable(err, policy.nonRetryable))
|
|
66
183
|
throw err;
|
|
67
|
-
|
|
68
|
-
|
|
184
|
+
// The UN-JITTERED backoff, which is a pure function of the declared policy
|
|
185
|
+
// and the attempt index — and which is therefore what the park decision
|
|
186
|
+
// below turns on. Deciding on the jittered value instead would put
|
|
187
|
+
// `Math.random()` on a control-flow branch inside a determinism contract:
|
|
188
|
+
// the same attempt could sleep on one pass and park on the next, for no
|
|
189
|
+
// reason a reader of the manifest could see. It would also make the static
|
|
190
|
+
// check unstateable, since the analyzer cannot know which way a coin
|
|
191
|
+
// landed. Jitter still does its whole job — spreading re-attempts — on the
|
|
192
|
+
// duration itself, in both branches.
|
|
193
|
+
const backoff = retryBackoffMs(policy, resend);
|
|
194
|
+
const delay = jitter === "full" ? Math.random() * backoff : backoff;
|
|
195
|
+
// A LONG backoff inside a durable run suspends rather than sleeps, and the
|
|
196
|
+
// attempt state is journaled with it. The obvious reading — only the
|
|
197
|
+
// outcome matters, so journal once — is wrong the moment a backoff
|
|
198
|
+
// suspends: a run that parks mid-retry and resumes in another process must
|
|
199
|
+
// know which attempt it was on, or it restarts the policy from zero and a
|
|
200
|
+
// three-attempt cap becomes unbounded.
|
|
201
|
+
//
|
|
202
|
+
// ONE DECISION PER ATTEMPT, holding when that attempt was due, is the
|
|
203
|
+
// whole mechanism. It needs nothing beyond `decide`: on resume the loop
|
|
204
|
+
// re-runs from attempt zero, each recorded attempt hands back a due time
|
|
205
|
+
// already in the past and is therefore consumed without waiting, and the
|
|
206
|
+
// first UNRECORDED attempt computes a fresh one and parks. The budget is
|
|
207
|
+
// preserved because the replayed attempts still count against it.
|
|
208
|
+
if (handle && backoff >= SUSPENDING_BACKOFF_MS) {
|
|
209
|
+
const attemptPath = stepPath(path, "retry", resend);
|
|
210
|
+
const dueAt = (await handle.decide(attemptPath, "value", () => Date.now() + delay));
|
|
211
|
+
if (Date.now() < dueAt) {
|
|
212
|
+
// Refused inside a region that promised nothing in it suspends. The
|
|
213
|
+
// check is here rather than at the policy, because a short backoff
|
|
214
|
+
// never suspends and rejecting one would forbid a retry that is
|
|
215
|
+
// perfectly safe in a lease.
|
|
216
|
+
assertMaySuspend(ctx, invokeCtx, { resource: step.name ?? path });
|
|
217
|
+
await parkRun(handle, { path: attemptPath, resource: step.name ?? path }, { at: dueAt });
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
await waitBeforeResend(delay, invokeCtx?.cancellation, step, err);
|
|
69
222
|
}
|
|
70
223
|
}
|
|
71
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* The backoff before attempt `resend + 1`, before jitter.
|
|
227
|
+
*
|
|
228
|
+
* ONE formula, exported because the analyzer needs the same number: it decides
|
|
229
|
+
* statically whether a step's declared policy would park inside a region that
|
|
230
|
+
* cannot be held open, and a second copy of exponential-backoff arithmetic in
|
|
231
|
+
* the analyzer would be a rule that drifts from the behaviour it describes the
|
|
232
|
+
* first time either side gains a knob.
|
|
233
|
+
*
|
|
234
|
+
* Jitter is deliberately NOT applied here. It belongs to the duration, not to
|
|
235
|
+
* the shape of the policy, and the two consumers want the shape: the runtime
|
|
236
|
+
* branches on it (see `withStepRetry`) and the analyzer reports on it.
|
|
237
|
+
*
|
|
238
|
+
* The `??` fallbacks are the floor for a caller that assembled a policy in code;
|
|
239
|
+
* a manifest gets its defaults from the schema.
|
|
240
|
+
*/
|
|
241
|
+
export function retryBackoffMs(policy, resend) {
|
|
242
|
+
const initial = policy.initialDelay ?? parseDuration(policy.delay) ?? 250;
|
|
243
|
+
const factor = policy.factor ?? 2;
|
|
244
|
+
const maxDelay = policy.maxDelay ?? 32_000;
|
|
245
|
+
return Math.min(maxDelay, initial * Math.pow(factor, resend));
|
|
246
|
+
}
|
|
72
247
|
/** Kernel verdicts on the CALL rather than on the work, beyond the ambient
|
|
73
248
|
* contract set. A dispatch that cannot resolve its target is a manifest defect;
|
|
74
249
|
* re-issuing it re-resolves the same name against the same registry. */
|
|
75
250
|
const UNRETRYABLE_CODES = new Set(["ERR_RESOURCE_NOT_FOUND", "ERR_RESOURCE_NOT_INVOKABLE"]);
|
|
76
|
-
function isRetryable(err) {
|
|
251
|
+
function isRetryable(err, nonRetryable) {
|
|
77
252
|
if (isCancellationError(err))
|
|
78
253
|
return false;
|
|
254
|
+
// A suspension is not a failure — it is the run leaving. Re-attempting it
|
|
255
|
+
// would park again under the same policy until the budget ran out, and the
|
|
256
|
+
// last attempt would propagate a park the earlier ones had already recorded.
|
|
257
|
+
if (isSuspension(err))
|
|
258
|
+
return false;
|
|
79
259
|
const code = err?.code;
|
|
80
260
|
if (typeof code !== "string")
|
|
81
261
|
return true;
|
|
262
|
+
// The author's own exclusions, checked beside the built-in ones rather than
|
|
263
|
+
// before or after them: they are the same question — is re-issuing this call
|
|
264
|
+
// capable of a different answer — asked about a domain failure the leaf has no
|
|
265
|
+
// way to classify. A step timeout is never in this set by default; whether a
|
|
266
|
+
// slow call is worth re-attempting is exactly the judgement an author makes.
|
|
267
|
+
if (nonRetryable?.includes(code))
|
|
268
|
+
return false;
|
|
82
269
|
return !isAmbientContractErrorCode(code) && !UNRETRYABLE_CODES.has(code);
|
|
83
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Bound ONE attempt, by cancellation rather than by abandonment.
|
|
273
|
+
*
|
|
274
|
+
* A `Promise.race` that simply rejects would leave the call running, holding its
|
|
275
|
+
* connection and eventually completing a side effect nobody is waiting on — the
|
|
276
|
+
* failure mode a timeout is usually adopted to prevent. So a timeout mints a
|
|
277
|
+
* cancellation source, LINKS it to the caller's token (or the caller's
|
|
278
|
+
* cancellation would stop propagating the moment a step declared a bound), and
|
|
279
|
+
* threads its context into the dispatch. A target that honours cancellation
|
|
280
|
+
* stops; one that does not is no worse off than before.
|
|
281
|
+
*
|
|
282
|
+
* The elapse is reported as `ERR_STEP_TIMEOUT` rather than as a cancellation,
|
|
283
|
+
* because the two want opposite follow-ups: a cancelled run was asked to stop,
|
|
284
|
+
* while a timed-out step is a target that is too slow for this call site — and
|
|
285
|
+
* `catches:` can only tell them apart if they carry different codes.
|
|
286
|
+
*/
|
|
287
|
+
async function withStepTimeout(step, invokeCtx, dispatch) {
|
|
288
|
+
const ms = step.timeout;
|
|
289
|
+
if (ms === undefined || !(ms > 0))
|
|
290
|
+
return dispatch(invokeCtx);
|
|
291
|
+
const source = createCancellationSource();
|
|
292
|
+
const base = invokeCtx ?? UNCANCELLABLE_CONTEXT;
|
|
293
|
+
// Everything else on the context — zones, tracing, and whatever a later
|
|
294
|
+
// member adds — rides across unchanged. Rebuilding it as a literal here is
|
|
295
|
+
// the drop `deriveContext` exists to prevent.
|
|
296
|
+
const scoped = deriveContext(base, { cancellation: source.token });
|
|
297
|
+
const unlink = invokeCtx?.cancellation.onCancelled((reason) => source.cancel(reason));
|
|
298
|
+
let elapsed = false;
|
|
299
|
+
source.cancelAfter(ms);
|
|
300
|
+
const timedOut = source.token.onCancelled(() => {
|
|
301
|
+
if (!invokeCtx?.cancellation.isCancelled)
|
|
302
|
+
elapsed = true;
|
|
303
|
+
});
|
|
304
|
+
try {
|
|
305
|
+
return await dispatch(scoped);
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
if (elapsed && isCancellationError(err)) {
|
|
309
|
+
throw new InvokeError("ERR_STEP_TIMEOUT", `Step '${step.name}' exceeded its timeout of ${ms}ms and was cancelled`, { step: step.name, timeout: ms });
|
|
310
|
+
}
|
|
311
|
+
throw err;
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
timedOut();
|
|
315
|
+
unlink?.();
|
|
316
|
+
// Releases the pending deadline timer, so a step that finished early does
|
|
317
|
+
// not pin a timer alive until its bound elapses.
|
|
318
|
+
source.dispose();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
84
321
|
/**
|
|
85
322
|
* Wait out the backoff, or give up the moment the invocation is cancelled.
|
|
86
323
|
*
|
|
@@ -134,6 +371,12 @@ function parseDuration(value) {
|
|
|
134
371
|
}
|
|
135
372
|
async function dispatch(raw, inputs, ctx, state) {
|
|
136
373
|
let result;
|
|
374
|
+
// The context this attempt runs under: the step's timeout scope when it
|
|
375
|
+
// declares one, else whatever the composer forwarded. Threaded explicitly
|
|
376
|
+
// rather than installed as ambient because the SDK leaf has no ambient store
|
|
377
|
+
// to install into — that is one runtime's mechanism, and a second-language
|
|
378
|
+
// leaf has no `AsyncLocalStorage`.
|
|
379
|
+
const attemptCtx = state.invokeCtx;
|
|
137
380
|
if (raw && typeof raw.invoke === "function") {
|
|
138
381
|
// A pre-injected live instance (a `!ref` resolved at Phase 5). Route it
|
|
139
382
|
// through the traced chokepoint using the identity the kernel stamped at
|
|
@@ -141,8 +384,8 @@ async function dispatch(raw, inputs, ctx, state) {
|
|
|
141
384
|
// A truly anonymous instance (no stamp) falls back to a direct call.
|
|
142
385
|
const identity = getRefIdentity(raw);
|
|
143
386
|
result = identity
|
|
144
|
-
? await ctx.invokeResolved(identity.kind, identity.name, raw, inputs)
|
|
145
|
-
: await raw.invoke(inputs);
|
|
387
|
+
? await ctx.invokeResolved(identity.kind, identity.name, raw, inputs, attemptCtx)
|
|
388
|
+
: await raw.invoke(inputs, attemptCtx);
|
|
146
389
|
}
|
|
147
390
|
else {
|
|
148
391
|
const ref = raw;
|
|
@@ -154,14 +397,14 @@ async function dispatch(raw, inputs, ctx, state) {
|
|
|
154
397
|
if (!instance) {
|
|
155
398
|
throw new Error(`Cross-module reference '${ref.alias}.${ref.name}' did not resolve to an exported instance.`);
|
|
156
399
|
}
|
|
157
|
-
result = await ctx.invokeResolved(ref.kind, ref.name, instance, inputs);
|
|
400
|
+
result = await ctx.invokeResolved(ref.kind, ref.name, instance, inputs, attemptCtx);
|
|
158
401
|
}
|
|
159
402
|
else if (state.scope) {
|
|
160
403
|
const instance = state.scope.getInstance(ref.name);
|
|
161
|
-
result = await ctx.invokeResolved(ref.kind, ref.name, instance, inputs);
|
|
404
|
+
result = await ctx.invokeResolved(ref.kind, ref.name, instance, inputs, attemptCtx);
|
|
162
405
|
}
|
|
163
406
|
else {
|
|
164
|
-
result = await ctx.invoke(ref.kind, ref.name, inputs);
|
|
407
|
+
result = await ctx.invoke(ref.kind, ref.name, inputs, { ctx: attemptCtx });
|
|
165
408
|
}
|
|
166
409
|
}
|
|
167
410
|
return result;
|
|
@@ -11,6 +11,7 @@ import { ResourceInstance } from "./resource-instance.js";
|
|
|
11
11
|
import { ResourceManifest } from "./resource-manifest.js";
|
|
12
12
|
import { RuntimeResource } from "./runtime-resource.js";
|
|
13
13
|
import type { RuntimeSeam } from "./runtime-seam.js";
|
|
14
|
+
import type { OpenZoneAttributes } from "./zone-attribute.js";
|
|
14
15
|
export interface LoadOptions {
|
|
15
16
|
/** When true, `${{ }}` templates are replaced with CompiledValue wrappers
|
|
16
17
|
* so they can be evaluated at runtime. Leave unset for static analysis. */
|
|
@@ -130,6 +131,28 @@ export interface ResourceContext extends ControllerContext {
|
|
|
130
131
|
* one). No kind parameter: the provider's own per-instance map already
|
|
131
132
|
* discriminates — a zone this instance's owner did not open simply misses. */
|
|
132
133
|
zonesFor(instance: ResourceInstance, ctx?: InvokeContext): readonly ZoneEntry[];
|
|
134
|
+
/**
|
|
135
|
+
* Every open zone with what it DECLARES about its contents, innermost first —
|
|
136
|
+
* the runtime half of `x-telo-provides-zone`'s attributes.
|
|
137
|
+
*
|
|
138
|
+
* Read off the declaring kind's schema, never off the entry: a
|
|
139
|
+
* {@link ZoneEntry} is three identities *because* that keeps it
|
|
140
|
+
* ABI-serializable and stops any module reading another's private state off
|
|
141
|
+
* the stack, and hanging attributes on it would trade that away for every
|
|
142
|
+
* zone. The kernel resolves the schema instead — the one place that lookup is
|
|
143
|
+
* already available — and hands the attributes over WITHOUT branching on a
|
|
144
|
+
* name, exactly as `readRefSlot` returns `use` without acting on it.
|
|
145
|
+
*
|
|
146
|
+
* The vocabulary is closed (`sdk/zone-attributes/`), which is what lets this
|
|
147
|
+
* be a typed record rather than a string-keyed bag. That is a readability
|
|
148
|
+
* gain and not a semantic one: interpreting an attribute is entirely the
|
|
149
|
+
* caller's — the step engine reads `atomic` to decide collapse, a parking kind
|
|
150
|
+
* reads `noSuspend` to refuse, and the kernel reads neither.
|
|
151
|
+
*
|
|
152
|
+
* Each value is the author's REASON, so a controller refusing on an attribute
|
|
153
|
+
* quotes the manifest's own sentence instead of inventing a generic message.
|
|
154
|
+
*/
|
|
155
|
+
zoneAttributes(ctx?: InvokeContext): readonly OpenZoneAttributes[];
|
|
133
156
|
/** The root context for runtime-driven inbound work (request, timer, queue
|
|
134
157
|
* message): inherits nothing from whatever ambient happens to be live at the
|
|
135
158
|
* registration site — no zones, no trace parent, no caller token. An inbound
|
|
@@ -191,6 +214,20 @@ export interface ResourceContext extends ControllerContext {
|
|
|
191
214
|
* says what was missing.
|
|
192
215
|
*/
|
|
193
216
|
resolveRef<T>(value: unknown, guard: (candidate: unknown) => candidate is T, describe: () => string, expects?: string): T;
|
|
217
|
+
/**
|
|
218
|
+
* The manifest a name was DECLARED with, resolved in the context that OWNS
|
|
219
|
+
* this resource — the same order {@link resolveRef} uses, so a declaration
|
|
220
|
+
* lookup cannot disagree with an instance lookup about what a name means.
|
|
221
|
+
*
|
|
222
|
+
* The counterpart to {@link resolveRef} for a slot that wants a FACT about its
|
|
223
|
+
* target rather than the target itself. A declaration is readable whether or
|
|
224
|
+
* not the resource has been constructed, which is what lets such a slot avoid
|
|
225
|
+
* an ordering edge — and what lets a resource read a slot pointing at itself.
|
|
226
|
+
*
|
|
227
|
+
* Optional because a third-party context implementation must keep compiling;
|
|
228
|
+
* absent reads as "no declaration in scope".
|
|
229
|
+
*/
|
|
230
|
+
resolveDeclaredManifest?(name: string, alias?: string): ResourceManifest | undefined;
|
|
194
231
|
validateSchema(value: any, schema: any): void;
|
|
195
232
|
/** Compile an author-written JSON Schema from a resource field into a
|
|
196
233
|
* reusable validator, through the runtime's own engine — so its formats and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-context.d.ts","sourceRoot":"","sources":["../src/resource-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,QAAQ,EACR,eAAe,EACf,SAAS,EACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"resource-context.d.ts","sourceRoot":"","sources":["../src/resource-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,26 @@ export declare const TEARDOWN_LAST = 1000;
|
|
|
28
28
|
export interface RefIdentity {
|
|
29
29
|
kind: string;
|
|
30
30
|
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* Where the instance was DECLARED, for a consumer that must name it somewhere
|
|
33
|
+
* the instance does not exist — a durable step shipped to another process.
|
|
34
|
+
*
|
|
35
|
+
* Optional because it is derived from the declaration and an instance stamped
|
|
36
|
+
* by a path that has none is still dispatchable; a consumer that genuinely
|
|
37
|
+
* needs it refuses rather than guessing (see `encodeDurableTarget`). Kept ON
|
|
38
|
+
* the identity rather than in a second table because it answers the same
|
|
39
|
+
* question the identity does — *which declaration is this* — one level more
|
|
40
|
+
* precisely.
|
|
41
|
+
*/
|
|
42
|
+
origin?: RefOrigin;
|
|
43
|
+
}
|
|
44
|
+
/** The declaration site behind a live instance. `module` is the source of the
|
|
45
|
+
* module that declared it, which is what tells two libraries' same-named
|
|
46
|
+
* resources apart; `pointer` is set when the declaration is inline, and is a
|
|
47
|
+
* JSON pointer into its declaring resource. */
|
|
48
|
+
export interface RefOrigin {
|
|
49
|
+
module?: string;
|
|
50
|
+
pointer?: string;
|
|
31
51
|
}
|
|
32
52
|
/**
|
|
33
53
|
* Kernel-minted, unique per LIVE instance, stable for its lifetime. Distinct
|
|
@@ -59,7 +79,7 @@ export declare const sameResource: (a: ResourceHandle, b: ResourceHandle) => boo
|
|
|
59
79
|
export declare const REF_IDENTITY: unique symbol;
|
|
60
80
|
/** Stamp the resolved kind+name onto an injected instance. Idempotent — an
|
|
61
81
|
* instance has exactly one identity, so re-injection into other slots is a no-op. */
|
|
62
|
-
export declare function stampRefIdentity(instance: object, kind: string, name: string): void;
|
|
82
|
+
export declare function stampRefIdentity(instance: object, kind: string, name: string, origin?: RefOrigin): void;
|
|
63
83
|
/** Read the identity stamped by {@link stampRefIdentity}, if any. */
|
|
64
84
|
export declare function getRefIdentity(instance: object): RefIdentity | undefined;
|
|
65
85
|
//# sourceMappingURL=resource-instance.d.ts.map
|
|
@@ -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;
|
|
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;IACb;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED;;;gDAGgD;AAChD,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;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,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,SAAS,GACjB,IAAI,CAaN;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExE"}
|
|
@@ -13,10 +13,14 @@ export const sameResource = (a, b) => a.id === b.id;
|
|
|
13
13
|
export const REF_IDENTITY = Symbol.for("telo.refIdentity");
|
|
14
14
|
/** Stamp the resolved kind+name onto an injected instance. Idempotent — an
|
|
15
15
|
* instance has exactly one identity, so re-injection into other slots is a no-op. */
|
|
16
|
-
export function stampRefIdentity(instance, kind, name) {
|
|
16
|
+
export function stampRefIdentity(instance, kind, name, origin) {
|
|
17
17
|
if (!(REF_IDENTITY in instance)) {
|
|
18
18
|
Object.defineProperty(instance, REF_IDENTITY, {
|
|
19
|
-
value: {
|
|
19
|
+
value: {
|
|
20
|
+
kind,
|
|
21
|
+
name,
|
|
22
|
+
...(origin && (origin.module || origin.pointer) ? { origin } : {}),
|
|
23
|
+
},
|
|
20
24
|
enumerable: false,
|
|
21
25
|
configurable: true,
|
|
22
26
|
writable: false,
|