@nimbus-sh/fabric 0.7.1 → 0.8.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/bindings.d.ts +1 -0
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +2 -0
- package/dist/connections.d.ts +1 -1
- package/dist/connections.js +1 -1
- package/dist/do-calls.d.ts +71 -9
- package/dist/do-calls.d.ts.map +1 -1
- package/dist/do-calls.js +148 -22
- package/dist/facet-pool.d.ts +3 -0
- package/dist/facet-pool.d.ts.map +1 -1
- package/dist/facet-pool.js +3 -0
- package/dist/fanout.d.ts.map +1 -1
- package/dist/fanout.js +4 -3
- package/dist/fenced-work.d.ts +3 -3
- package/dist/image-store.js +2 -2
- package/dist/inner-do-registry.d.ts +9 -0
- package/dist/inner-do-registry.d.ts.map +1 -1
- package/dist/inner-do-registry.js +35 -0
- package/dist/isolate-pool.d.ts +1 -1
- package/dist/isolate-pool.d.ts.map +1 -1
- package/dist/isolate-pool.js +10 -8
- package/dist/process-fabric.d.ts +16 -12
- package/dist/process-fabric.d.ts.map +1 -1
- package/dist/process-fabric.js +18 -6
- package/dist/process-host.d.ts +3 -1
- package/dist/process-host.d.ts.map +1 -1
- package/dist/process-host.js +13 -14
- package/dist/supervisor-props.d.ts +47 -0
- package/dist/supervisor-props.d.ts.map +1 -0
- package/dist/supervisor-props.js +37 -0
- package/dist/workerd-facet-host.d.ts +4 -17
- package/dist/workerd-facet-host.d.ts.map +1 -1
- package/dist/workerd-facet-host.js +95 -29
- package/package.json +5 -5
- package/src/bindings.ts +2 -0
- package/src/connections.ts +1 -1
- package/src/do-calls.ts +182 -25
- package/src/facet-pool.ts +5 -0
- package/src/fanout.ts +4 -3
- package/src/fenced-work.ts +3 -3
- package/src/image-store.ts +2 -2
- package/src/inner-do-registry.ts +31 -0
- package/src/isolate-pool.ts +10 -8
- package/src/process-fabric.ts +33 -17
- package/src/process-host.ts +16 -14
- package/src/supervisor-props.ts +56 -0
- package/src/workerd-facet-host.ts +96 -32
package/dist/bindings.d.ts
CHANGED
|
@@ -113,6 +113,7 @@ declare const NimbusLoadedEntrypointPropsSchema: z.ZodObject<{
|
|
|
113
113
|
hostNamespace: z.ZodString;
|
|
114
114
|
hostDispatchMethod: z.ZodString;
|
|
115
115
|
}, z.core.$strip>>;
|
|
116
|
+
hostIncarnation: z.ZodOptional<z.ZodString>;
|
|
116
117
|
}, z.core.$strip>>;
|
|
117
118
|
stage: z.ZodOptional<z.ZodUnknown>;
|
|
118
119
|
}, z.core.$loose>;
|
package/dist/bindings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAG3B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAIlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAcpD;;;;GAIG;AACH,UAAU,gBAAgB;IACxB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3C,iBAAiB,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzD;AAED,4EAA4E;AAC5E,UAAU,YAAY;IACpB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC;IAC/C,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAAC;CACzD;AAED;;;;;;GAMG;AACH,UAAU,iBAAiB;IACzB,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAAC;IACrC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC;CAC/D;AAED;;;;GAIG;AACH,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;CACpC;AAyBD,4CAA4C;AAC5C,UAAU,iBAAiB;IACzB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,eAAgB,SAAQ,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAC9E;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;CAyEjD;AAiGD,QAAA,MAAM,iCAAiC
|
|
1
|
+
{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"}
|
package/dist/bindings.js
CHANGED
|
@@ -255,6 +255,8 @@ const NimbusLoadedEntrypointPropsSchema = z.object({
|
|
|
255
255
|
pid: z.number().int().nonnegative(),
|
|
256
256
|
writerId: z.string().uuid(),
|
|
257
257
|
route: HostRouteSchema.optional(),
|
|
258
|
+
/** The host instance's delivery incarnation (ResidentSupervisorProps). */
|
|
259
|
+
hostIncarnation: z.string().uuid().optional(),
|
|
258
260
|
}).optional(),
|
|
259
261
|
/**
|
|
260
262
|
* Staged-artifact spec, for a ONE-SHOT run. The module map — ~23 MB for
|
package/dist/connections.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* state over the WebSocket attachment.
|
|
4
4
|
*
|
|
5
5
|
* Specified from Proteus's DeviceSocketHub (`cf-backend/src/user/device-hub.ts`)
|
|
6
|
-
* and CLI rpc gate (`cf-backend/src/cli/rpc-gate.ts`), which split the
|
|
6
|
+
* and its original CLI rpc gate (`cf-backend/src/cli/rpc-gate.ts`), which split the
|
|
7
7
|
* pattern into its two halves:
|
|
8
8
|
* - a TAG is the immutable-at-accept lookup key and authorization — it
|
|
9
9
|
* rides the hibernation state, which is why the rpc gate persists auth
|
package/dist/connections.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* state over the WebSocket attachment.
|
|
4
4
|
*
|
|
5
5
|
* Specified from Proteus's DeviceSocketHub (`cf-backend/src/user/device-hub.ts`)
|
|
6
|
-
* and CLI rpc gate (`cf-backend/src/cli/rpc-gate.ts`), which split the
|
|
6
|
+
* and its original CLI rpc gate (`cf-backend/src/cli/rpc-gate.ts`), which split the
|
|
7
7
|
* pattern into its two halves:
|
|
8
8
|
* - a TAG is the immutable-at-accept lookup key and authorization — it
|
|
9
9
|
* rides the hibernation state, which is why the rpc gate persists auth
|
package/dist/do-calls.d.ts
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* the one property that decides whether a retry is safe.
|
|
4
4
|
*
|
|
5
5
|
* Both consumers asked for this. Proteus hand-wrote the retry
|
|
6
|
-
* (`cf-backend/src/lib/do-rpc.ts`) with the rule its header states:
|
|
6
|
+
* (originally `cf-backend/src/lib/do-rpc.ts`) with the rule its header states:
|
|
7
7
|
* "An operation that appends, sends, charges or mints is never wrapped: a
|
|
8
8
|
* dropped call there may already have run, so a retry is a correctness bug
|
|
9
9
|
* wearing resilience as a costume." agent-core has no retry machinery at all
|
|
10
10
|
* and its backlog calls the gap "the most production-proven gap in the
|
|
11
11
|
* corpus". Here the rule is a type: `idempotent` retries, `mutating` cannot.
|
|
12
|
+
* A mutation earns a retry only by carrying an identity its callee applies
|
|
13
|
+
* at most once; it is then `idempotent` by construction (see `mutating`).
|
|
12
14
|
*
|
|
13
15
|
* What the platform contract requires, and this keeps:
|
|
14
16
|
* - a FRESH stub per attempt. Cloudflare documents that many exceptions
|
|
@@ -20,6 +22,11 @@
|
|
|
20
22
|
* object is what overloaded it.
|
|
21
23
|
* - attempts and backoff are the consumer-proven bounds: 3 attempts total,
|
|
22
24
|
* full-jitter delays in [0, 2**attempt * 60ms).
|
|
25
|
+
* - an `idempotent` call may also be HEDGED (`hedgeAfterMs`): an attempt
|
|
26
|
+
* that has not answered by then is joined by the same call on a fresh
|
|
27
|
+
* stub, both left running, the first success taken. Hedges count
|
|
28
|
+
* against the attempts, and a callee that joins a repeat to the call it
|
|
29
|
+
* is already serving makes one that did arrive cost nothing.
|
|
23
30
|
*
|
|
24
31
|
* The resolver MINTS a stub per call and the verb disposes each one it
|
|
25
32
|
* minted — that ownership is what makes the fresh-stub retry real.
|
|
@@ -37,10 +44,38 @@ export interface DoCallRetryPolicy {
|
|
|
37
44
|
maxAttempts?: number;
|
|
38
45
|
baseDelayMs?: number;
|
|
39
46
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
47
|
+
* No repeat — retry or hedge — starts once this long has passed since the
|
|
48
|
+
* first attempt did; the failure in hand surfaces instead. A mutation made
|
|
49
|
+
* repeatable by an identity its callee dedupes needs it: the callee keeps
|
|
50
|
+
* what answers a repeat for a bounded time, so the caller's repeats must
|
|
51
|
+
* stop well inside it. Unbounded when absent.
|
|
52
|
+
*/
|
|
53
|
+
retryWindowMs?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Hedge an attempt that has not answered after this long: send the same
|
|
56
|
+
* call again on a fresh stub while the first stays in flight. The caller
|
|
57
|
+
* gets the first success; an answer after it is disposed and dropped. That
|
|
58
|
+
* is only harmless when a second delivery of the call changes nothing — a
|
|
59
|
+
* read — and cheap only when the callee joins a repeat to the call it is
|
|
60
|
+
* already serving. A hedge is an attempt: it counts against `maxAttempts`,
|
|
61
|
+
* and has its own deadline. Never hedged when absent.
|
|
62
|
+
*
|
|
63
|
+
* With attempts overlapping, a failure decides less. A retryable one is
|
|
64
|
+
* retried after its backoff while attempts remain, and `overloaded` stops
|
|
65
|
+
* every further repeat; either way the call keeps waiting on the attempts
|
|
66
|
+
* still in flight, and fails with the last failure only once none is. Any
|
|
67
|
+
* other failure is the callee's answer — the call ran — and is the call's
|
|
68
|
+
* at once.
|
|
69
|
+
*/
|
|
70
|
+
hedgeAfterMs?: number;
|
|
71
|
+
/**
|
|
72
|
+
* Called once per retry, as it starts — after its backoff delay — with the
|
|
73
|
+
* failure the retry is answering. A retry a hedge made unnecessary, or
|
|
74
|
+
* that no attempt is left for, is never announced. The consumer's logging
|
|
75
|
+
* seam: Proteus's hand-rolled predecessor logged every retry so a flaky
|
|
76
|
+
* object is visible in Workers Logs rather than silently absorbed, and
|
|
77
|
+
* `operation` names it there. A callback that throws fails the call with
|
|
78
|
+
* its error.
|
|
44
79
|
*/
|
|
45
80
|
onRetry?(info: DoCallRetryInfo): void;
|
|
46
81
|
}
|
|
@@ -49,7 +84,10 @@ export interface DoCallRetryPolicy {
|
|
|
49
84
|
export interface DoCallRetryInfo {
|
|
50
85
|
operation: string;
|
|
51
86
|
classification: DoCallClass;
|
|
52
|
-
/**
|
|
87
|
+
/**
|
|
88
|
+
* The 1-based number of the attempt that failed. Without hedging the retry
|
|
89
|
+
* is attempt+1; with it, other attempts may have started in between.
|
|
90
|
+
*/
|
|
53
91
|
attempt: number;
|
|
54
92
|
maxAttempts: number;
|
|
55
93
|
error: unknown;
|
|
@@ -79,9 +117,18 @@ export declare class DoCallError extends Error {
|
|
|
79
117
|
}
|
|
80
118
|
/**
|
|
81
119
|
* Call another Durable Object with an operation that is safe to repeat: a
|
|
82
|
-
* read,
|
|
83
|
-
*
|
|
84
|
-
*
|
|
120
|
+
* read, a converge-to-a-value write, or a mutation carrying an identity its
|
|
121
|
+
* callee applies at most once (see {@link mutating}). Transient failures
|
|
122
|
+
* retry on a fresh stub with full-jitter backoff; overloaded and permanent
|
|
123
|
+
* failures surface unchanged, as does the last error once no attempt may be
|
|
124
|
+
* repeated — attempts spent, or the policy's retry window closed. With
|
|
125
|
+
* `hedgeAfterMs`, an attempt still unanswered by then is joined by another
|
|
126
|
+
* on a fresh stub, and the first answer is taken: a success, or the
|
|
127
|
+
* callee's own error. A transient or overloaded failure then ends the call
|
|
128
|
+
* only once no attempt is left in flight.
|
|
129
|
+
*
|
|
130
|
+
* A failure of the resolver or of `onRetry` is the caller's own, and fails
|
|
131
|
+
* the call with it at once.
|
|
85
132
|
*/
|
|
86
133
|
export declare function idempotent<S, T>(operation: string, stub: DoStubResolver<S>, call: (stub: S) => Promise<T>, policy?: DoCallRetryPolicy): Promise<T>;
|
|
87
134
|
/**
|
|
@@ -89,6 +136,21 @@ export declare function idempotent<S, T>(operation: string, stub: DoStubResolver
|
|
|
89
136
|
* or mints. NEVER retried — a dropped call may already have run. Failure
|
|
90
137
|
* surfaces as a {@link DoCallError} carrying the classification, so the
|
|
91
138
|
* caller can tell a refusal from an indeterminate drop.
|
|
139
|
+
*
|
|
140
|
+
* The rule is about the call as sent, not the operation's kind. A mutation
|
|
141
|
+
* the callee applies at most once per identity the call carries is
|
|
142
|
+
* repeatable by construction: a repeat of one that already ran is answered
|
|
143
|
+
* from the callee's record and applies nothing. Nimbus has two:
|
|
144
|
+
* - delivered filesystem mutations (@nimbus-sh/core supervisor-delivery):
|
|
145
|
+
* a delivery id plus the callee INSTANCE's incarnation. The record lives
|
|
146
|
+
* in that instance's memory, and any other instance — or a callee that
|
|
147
|
+
* predates delivery — refuses the call permanently rather than apply it
|
|
148
|
+
* without one;
|
|
149
|
+
* - appends: writer, module incarnation and operation sequence, recorded
|
|
150
|
+
* durably until acknowledged.
|
|
151
|
+
* Such a call goes through {@link idempotent}, re-sending the same identity
|
|
152
|
+
* on every attempt, with a `retryWindowMs` inside the callee's retention of
|
|
153
|
+
* that record. Without such an identity, a mutation stays here.
|
|
92
154
|
*/
|
|
93
155
|
export declare function mutating<S, T>(operation: string, stub: DoStubResolver<S>, call: (stub: S) => Promise<T>): Promise<T>;
|
|
94
156
|
//# sourceMappingURL=do-calls.d.ts.map
|
package/dist/do-calls.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"do-calls.d.ts","sourceRoot":"","sources":["../src/do-calls.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"do-calls.d.ts","sourceRoot":"","sources":["../src/do-calls.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAU1G,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,OAAO,CAAC,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;CACvC;AAED;2CAC2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,WAAW,CAAC;IAC5B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAErD;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU;IACxC,QAAQ,CAAC,cAAc,EAAE,WAAW;gBAF3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,GAAG,UAAU,EAC/B,cAAc,EAAE,WAAW,EACpC,KAAK,EAAE,OAAO;CASjB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EAC7B,MAAM,GAAE,iBAAsB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAmHZ;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,CAAC,EACjC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC5B,OAAO,CAAC,CAAC,CAAC,CAUZ"}
|
package/dist/do-calls.js
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* the one property that decides whether a retry is safe.
|
|
4
4
|
*
|
|
5
5
|
* Both consumers asked for this. Proteus hand-wrote the retry
|
|
6
|
-
* (`cf-backend/src/lib/do-rpc.ts`) with the rule its header states:
|
|
6
|
+
* (originally `cf-backend/src/lib/do-rpc.ts`) with the rule its header states:
|
|
7
7
|
* "An operation that appends, sends, charges or mints is never wrapped: a
|
|
8
8
|
* dropped call there may already have run, so a retry is a correctness bug
|
|
9
9
|
* wearing resilience as a costume." agent-core has no retry machinery at all
|
|
10
10
|
* and its backlog calls the gap "the most production-proven gap in the
|
|
11
11
|
* corpus". Here the rule is a type: `idempotent` retries, `mutating` cannot.
|
|
12
|
+
* A mutation earns a retry only by carrying an identity its callee applies
|
|
13
|
+
* at most once; it is then `idempotent` by construction (see `mutating`).
|
|
12
14
|
*
|
|
13
15
|
* What the platform contract requires, and this keeps:
|
|
14
16
|
* - a FRESH stub per attempt. Cloudflare documents that many exceptions
|
|
@@ -20,6 +22,11 @@
|
|
|
20
22
|
* object is what overloaded it.
|
|
21
23
|
* - attempts and backoff are the consumer-proven bounds: 3 attempts total,
|
|
22
24
|
* full-jitter delays in [0, 2**attempt * 60ms).
|
|
25
|
+
* - an `idempotent` call may also be HEDGED (`hedgeAfterMs`): an attempt
|
|
26
|
+
* that has not answered by then is joined by the same call on a fresh
|
|
27
|
+
* stub, both left running, the first success taken. Hedges count
|
|
28
|
+
* against the attempts, and a callee that joins a repeat to the call it
|
|
29
|
+
* is already serving makes one that did arrive cost nothing.
|
|
23
30
|
*
|
|
24
31
|
* The resolver MINTS a stub per call and the verb disposes each one it
|
|
25
32
|
* minted — that ownership is what makes the fresh-stub retry real.
|
|
@@ -64,38 +71,157 @@ export class DoCallError extends Error {
|
|
|
64
71
|
}
|
|
65
72
|
/**
|
|
66
73
|
* Call another Durable Object with an operation that is safe to repeat: a
|
|
67
|
-
* read,
|
|
68
|
-
*
|
|
69
|
-
*
|
|
74
|
+
* read, a converge-to-a-value write, or a mutation carrying an identity its
|
|
75
|
+
* callee applies at most once (see {@link mutating}). Transient failures
|
|
76
|
+
* retry on a fresh stub with full-jitter backoff; overloaded and permanent
|
|
77
|
+
* failures surface unchanged, as does the last error once no attempt may be
|
|
78
|
+
* repeated — attempts spent, or the policy's retry window closed. With
|
|
79
|
+
* `hedgeAfterMs`, an attempt still unanswered by then is joined by another
|
|
80
|
+
* on a fresh stub, and the first answer is taken: a success, or the
|
|
81
|
+
* callee's own error. A transient or overloaded failure then ends the call
|
|
82
|
+
* only once no attempt is left in flight.
|
|
83
|
+
*
|
|
84
|
+
* A failure of the resolver or of `onRetry` is the caller's own, and fails
|
|
85
|
+
* the call with it at once.
|
|
70
86
|
*/
|
|
71
|
-
export
|
|
87
|
+
export function idempotent(operation, stub, call, policy = {}) {
|
|
72
88
|
const maxAttempts = policy.maxAttempts ?? MAX_ATTEMPTS;
|
|
73
89
|
const baseDelayMs = policy.baseDelayMs ?? BASE_DELAY_MS;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
const { hedgeAfterMs, retryWindowMs } = policy;
|
|
91
|
+
const startedAt = Date.now();
|
|
92
|
+
// The executor form: fabric's library target predates Promise.withResolvers.
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const hedges = new Set();
|
|
95
|
+
let started = 0;
|
|
96
|
+
// Attempts in flight, or backing off before their retry: while one is,
|
|
97
|
+
// a failure is not the call's answer.
|
|
98
|
+
let live = 0;
|
|
99
|
+
// An attempt was shed as overloaded: nothing is repeated after it.
|
|
100
|
+
let refused = false;
|
|
101
|
+
let settled = false;
|
|
102
|
+
const settle = (answer) => {
|
|
103
|
+
if (settled)
|
|
104
|
+
return;
|
|
105
|
+
settled = true;
|
|
106
|
+
for (const timer of hedges)
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
hedges.clear();
|
|
109
|
+
answer();
|
|
110
|
+
};
|
|
111
|
+
/** May another attempt start at `at`? */
|
|
112
|
+
const canRepeat = (at) => !settled && !refused && started < maxAttempts
|
|
113
|
+
&& (retryWindowMs === undefined || at - startedAt <= retryWindowMs);
|
|
114
|
+
/** `error` ended an attempt that will not be repeated: the call's answer, once nothing else is live. */
|
|
115
|
+
const exhausted = (error) => {
|
|
116
|
+
if (live === 0)
|
|
117
|
+
settle(() => reject(error));
|
|
118
|
+
};
|
|
119
|
+
/** A failed attempt, numbered: repeat it after its backoff, or let it stand. */
|
|
120
|
+
const failed = async (number, error) => {
|
|
121
|
+
if (settled)
|
|
122
|
+
return;
|
|
84
123
|
const classification = classifyDoCall(error);
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
124
|
+
if (classification === 'overloaded') {
|
|
125
|
+
// A shed call is no answer: nothing more is sent, and an attempt
|
|
126
|
+
// still in flight may yet answer.
|
|
127
|
+
refused = true;
|
|
128
|
+
exhausted(error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!isRetryableDoCall(classification)) {
|
|
132
|
+
// The call ran and its answer is this error — ENOENT is a read's answer as much as bytes are.
|
|
133
|
+
settle(() => reject(error));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const delayMs = Math.floor(Math.random() * 2 ** number * baseDelayMs);
|
|
137
|
+
if (!canRepeat(Date.now() + delayMs)) {
|
|
138
|
+
exhausted(error);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
live++;
|
|
142
|
+
await new Promise((wake) => {
|
|
143
|
+
setTimeout(wake, delayMs);
|
|
90
144
|
});
|
|
91
|
-
|
|
92
|
-
|
|
145
|
+
live--;
|
|
146
|
+
// A hedge may have taken the last attempt, or answered, meanwhile.
|
|
147
|
+
if (!canRepeat(Date.now())) {
|
|
148
|
+
exhausted(error);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
policy.onRetry?.({ operation, classification, attempt: number, maxAttempts, error });
|
|
152
|
+
attempt();
|
|
153
|
+
};
|
|
154
|
+
const run = async () => {
|
|
155
|
+
const number = ++started;
|
|
156
|
+
live++;
|
|
157
|
+
const minted = await stub();
|
|
158
|
+
if (settled) {
|
|
159
|
+
live--;
|
|
160
|
+
disposeRpcResource(minted);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const hedge = hedgeAfterMs === undefined ? undefined : setTimeout(() => {
|
|
164
|
+
if (hedge !== undefined)
|
|
165
|
+
hedges.delete(hedge);
|
|
166
|
+
if (canRepeat(Date.now()))
|
|
167
|
+
attempt();
|
|
168
|
+
}, hedgeAfterMs);
|
|
169
|
+
if (hedge !== undefined)
|
|
170
|
+
hedges.add(hedge);
|
|
171
|
+
/** This attempt has its answer: it hedges no more, and its stub goes. */
|
|
172
|
+
const answered = () => {
|
|
173
|
+
if (hedge !== undefined) {
|
|
174
|
+
clearTimeout(hedge);
|
|
175
|
+
hedges.delete(hedge);
|
|
176
|
+
}
|
|
177
|
+
live--;
|
|
178
|
+
// A stub that threw may be permanently broken; none is ever reused.
|
|
179
|
+
disposeRpcResource(minted);
|
|
180
|
+
};
|
|
181
|
+
let result;
|
|
182
|
+
try {
|
|
183
|
+
result = await call(minted);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
answered();
|
|
187
|
+
await failed(number, error);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
answered();
|
|
191
|
+
if (settled) {
|
|
192
|
+
// Another attempt answered first: this answer is dropped, so nothing of it is kept.
|
|
193
|
+
disposeRpcResource(result);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
settle(() => resolve(result));
|
|
197
|
+
};
|
|
198
|
+
/** Start an attempt. Whatever it throws outside the call itself fails the call. */
|
|
199
|
+
const attempt = () => {
|
|
200
|
+
run().catch((error) => settle(() => reject(error)));
|
|
201
|
+
};
|
|
202
|
+
attempt();
|
|
203
|
+
});
|
|
93
204
|
}
|
|
94
205
|
/**
|
|
95
206
|
* Call another Durable Object with an operation that appends, sends, charges
|
|
96
207
|
* or mints. NEVER retried — a dropped call may already have run. Failure
|
|
97
208
|
* surfaces as a {@link DoCallError} carrying the classification, so the
|
|
98
209
|
* caller can tell a refusal from an indeterminate drop.
|
|
210
|
+
*
|
|
211
|
+
* The rule is about the call as sent, not the operation's kind. A mutation
|
|
212
|
+
* the callee applies at most once per identity the call carries is
|
|
213
|
+
* repeatable by construction: a repeat of one that already ran is answered
|
|
214
|
+
* from the callee's record and applies nothing. Nimbus has two:
|
|
215
|
+
* - delivered filesystem mutations (@nimbus-sh/core supervisor-delivery):
|
|
216
|
+
* a delivery id plus the callee INSTANCE's incarnation. The record lives
|
|
217
|
+
* in that instance's memory, and any other instance — or a callee that
|
|
218
|
+
* predates delivery — refuses the call permanently rather than apply it
|
|
219
|
+
* without one;
|
|
220
|
+
* - appends: writer, module incarnation and operation sequence, recorded
|
|
221
|
+
* durably until acknowledged.
|
|
222
|
+
* Such a call goes through {@link idempotent}, re-sending the same identity
|
|
223
|
+
* on every attempt, with a `retryWindowMs` inside the callee's retention of
|
|
224
|
+
* that record. Without such an identity, a mutation stays here.
|
|
99
225
|
*/
|
|
100
226
|
export async function mutating(operation, stub, call) {
|
|
101
227
|
const minted = await stub();
|
package/dist/facet-pool.d.ts
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* whichever acts second aborts or retires facets the other still tracks,
|
|
42
42
|
* and the facet-id ledger here counts only the names this pool minted.
|
|
43
43
|
*/
|
|
44
|
+
import type { SqlDatabase } from '@nimbus-sh/core/runtime/os-contracts.js';
|
|
44
45
|
/** `ctx.facets`, as the pool drives it — same surface the facet host uses. */
|
|
45
46
|
export interface FacetPoolContainer {
|
|
46
47
|
get(name: string, start: () => Promise<{
|
|
@@ -56,6 +57,8 @@ export interface FacetPoolContext {
|
|
|
56
57
|
storage: {
|
|
57
58
|
get(key: string): Promise<unknown> | unknown;
|
|
58
59
|
put(key: string, value: unknown): Promise<void>;
|
|
60
|
+
/** The session's SQL, where the storage ledger (N18) records facet databases. */
|
|
61
|
+
sql?: SqlDatabase;
|
|
59
62
|
};
|
|
60
63
|
}
|
|
61
64
|
/**
|
package/dist/facet-pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facet-pool.d.ts","sourceRoot":"","sources":["../src/facet-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;
|
|
1
|
+
{"version":3,"file":"facet-pool.d.ts","sourceRoot":"","sources":["../src/facet-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AAQ3E,8EAA8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC;IACrE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;wCACwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,OAAO,EAAE;QACP,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;QAC7C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,iFAAiF;QACjF,GAAG,CAAC,EAAE,WAAW,CAAC;KACnB,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,gEAAgE;IAChE,MAAM,IAAI,IAAI,CAAC;IACf,sEAAsE;IACtE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAKD,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAE1D;AAED,qBAAa,SAAS;IACR,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,gBAAgB;IAElD;;;;OAIG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,GACvC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;CAkD1B"}
|
package/dist/facet-pool.js
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* whichever acts second aborts or retires facets the other still tracks,
|
|
42
42
|
* and the facet-id ledger here counts only the names this pool minted.
|
|
43
43
|
*/
|
|
44
|
+
import { forgetFacetStorage } from '@nimbus-sh/core/runtime/storage-ledger.js';
|
|
44
45
|
import { FACET_ID_LIFETIME_BUDGET, facetNameCount, recordFacetNameMinted, withFacetBudgetNamed, } from './budgets.js';
|
|
45
46
|
/** Names this ctx's pool has already charged to the lifetime ledger. */
|
|
46
47
|
const chargedNames = new WeakMap();
|
|
@@ -93,6 +94,8 @@ export class FacetPool {
|
|
|
93
94
|
return;
|
|
94
95
|
try {
|
|
95
96
|
facets.delete(name);
|
|
97
|
+
if (this.ctx.storage.sql)
|
|
98
|
+
forgetFacetStorage(this.ctx.storage.sql, name);
|
|
96
99
|
}
|
|
97
100
|
catch (e) {
|
|
98
101
|
throw new Error(`fabric: facet '${name}' was evicted but its storage was not reclaimed — `
|
package/dist/fanout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fanout.d.ts","sourceRoot":"","sources":["../src/fanout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOtD;;+EAE+E;AAC/E,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,qBAAqB,UAAmB,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,UAAqB,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,uCAAuC;AACvC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,CAAC,CAAC;CACT;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC1C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAWD;;;;;;;;GAQG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,aAAa;IAoBzE;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,UAAU,CAAC,CAAC,EAAE,CAAC,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACtB,EAAE,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,EAAE,CAAC;IASf,mEAAmE;IACnE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO;IAK7D;;;;;;OAMG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;YAOvC,aAAa;YAoCb,eAAe;
|
|
1
|
+
{"version":3,"file":"fanout.d.ts","sourceRoot":"","sources":["../src/fanout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIlE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOtD;;+EAE+E;AAC/E,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;GAGG;AACH,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,qBAAqB,UAAmB,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,UAAqB,CAAC;AAE3D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,uCAAuC;AACvC,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,CAAC,CAAC;CACT;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC1C;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAWD;;;;;;;;GAQG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,aAAa;IAoBzE;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,UAAU,CAAC,CAAC,EAAE,CAAC,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACtB,EAAE,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,OAAO,CAAC,CAAC,EAAE,CAAC;IASf,mEAAmE;IACnE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO;IAK7D;;;;;;OAMG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;YAOvC,aAAa;YAoCb,eAAe;CA6J9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUrE"}
|
package/dist/fanout.js
CHANGED
|
@@ -18,7 +18,7 @@ import { BindingError } from './vendor/errors.js';
|
|
|
18
18
|
import { IsolatePool } from './isolate-pool.js';
|
|
19
19
|
import { hostRoute } from './composition.js';
|
|
20
20
|
import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
|
|
21
|
-
import {
|
|
21
|
+
import { classifyDoCall, describeError, isRetryableDoCall } from '@nimbus-sh/platform/oom-classify.js';
|
|
22
22
|
import { hostNamespaceBinding, hostOpDispatch, } from './host-dispatch.js';
|
|
23
23
|
/**
|
|
24
24
|
* Threshold at which routing switches from coordinator-local loaders to
|
|
@@ -297,8 +297,9 @@ export class Fanout {
|
|
|
297
297
|
return;
|
|
298
298
|
}
|
|
299
299
|
catch (err) {
|
|
300
|
-
const
|
|
301
|
-
|
|
300
|
+
const cls = classifyDoCall(err);
|
|
301
|
+
const schedule = cls === 'overloaded' ? PEER_OVERLOAD_BACKOFF_MS
|
|
302
|
+
: isRetryableDoCall(cls) ? PEER_RETRY_BACKOFF_MS
|
|
302
303
|
: null;
|
|
303
304
|
if (schedule && attempt < PEER_TRANSIENT_RESET_RETRIES) {
|
|
304
305
|
const backoff = schedule[Math.min(attempt, schedule.length - 1)];
|
package/dist/fenced-work.d.ts
CHANGED
|
@@ -53,9 +53,9 @@ export declare const FENCED_WORK_MAX_ATTEMPT = 1;
|
|
|
53
53
|
* (staging, 2026-08-13): every observed reset struck seconds AFTER the launch
|
|
54
54
|
* settled — the platform kills the object while the resident runs, which is
|
|
55
55
|
* when a launch-scoped row had already been deleted and recovery had nothing
|
|
56
|
-
* to find. A resident's facet
|
|
57
|
-
*
|
|
58
|
-
*
|
|
56
|
+
* to find. A resident's facet can outlive its session instance (a pending
|
|
57
|
+
* timer keeps it running), but nothing routes to it from the next one, and a
|
|
58
|
+
* spawn that takes its facet name ends it first.
|
|
59
59
|
*/
|
|
60
60
|
export interface FencedWorkRecord {
|
|
61
61
|
pid: number;
|
package/dist/image-store.js
CHANGED
|
@@ -111,12 +111,12 @@ export class ImageStore {
|
|
|
111
111
|
fs.mkdirp(FACET_IMAGE_DIR);
|
|
112
112
|
let count = 0;
|
|
113
113
|
for await (const [moduleName, source] of images) {
|
|
114
|
-
const
|
|
114
|
+
const bytes = new TextEncoder().encode(source);
|
|
115
|
+
const path = facetImagePath(await facetImageDigest(bytes));
|
|
115
116
|
paths[moduleName] = path;
|
|
116
117
|
rooted.push(path);
|
|
117
118
|
count++;
|
|
118
119
|
const stored = path.replace(/^\/+/, '');
|
|
119
|
-
const bytes = new TextEncoder().encode(source);
|
|
120
120
|
console.log('[image-store] pid=' + pid + ' image ' + count + ' ' + moduleName + ' → '
|
|
121
121
|
+ path.slice(-12) + ' ' + bytes.byteLength + ' bytes, slice=' + FACET_IMAGE_WRITE_SLICE_BYTES
|
|
122
122
|
+ ' turns=' + pacer.chunks);
|
|
@@ -38,4 +38,13 @@ export declare function getInnerDoClass(supervisorDoId: string, bindingName: str
|
|
|
38
38
|
export declare function registerInnerDoClass(supervisorDoId: string, bindingName: string, cls: DurableObjectClass): void;
|
|
39
39
|
/** Clear all registrations belonging to a supervisor DO (called on rebuild). */
|
|
40
40
|
export declare function clearInnerDoClasses(supervisorDoId: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Record that this incarnation opens `facetName` for `bindingName`. True on the
|
|
43
|
+
* name's first open since the incarnation began or the binding's facets were
|
|
44
|
+
* last aborted: whatever still runs under it has a class this build no longer
|
|
45
|
+
* uses, and a get() with the new class on it resets the whole object.
|
|
46
|
+
*/
|
|
47
|
+
export declare function noteInnerDoFacetOpened(ctx: DurableObjectState, bindingName: string, facetName: string): boolean;
|
|
48
|
+
/** Abort the facets this incarnation opened for `bindingNames`, keeping their storage, so each next request starts the class registered then. */
|
|
49
|
+
export declare function abortInnerDoFacets(ctx: DurableObjectState, bindingNames: Iterable<string>, reason: Error): void;
|
|
41
50
|
//# sourceMappingURL=inner-do-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inner-do-registry.d.ts","sourceRoot":"","sources":["../src/inner-do-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE3G;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,kBAAkB,GACtB,IAAI,CAEN;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAKhE"}
|
|
1
|
+
{"version":3,"file":"inner-do-registry.d.ts","sourceRoot":"","sources":["../src/inner-do-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE3G;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,kBAAkB,GACtB,IAAI,CAEN;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAKhE;AAKD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAQ/G;AAED,iJAAiJ;AACjJ,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI,CAS/G"}
|
|
@@ -49,3 +49,38 @@ export function clearInnerDoClasses(supervisorDoId) {
|
|
|
49
49
|
_NIMBUS_INNER_DO_CLASSES.delete(k);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
/** Inner-DO facet names each incarnation has opened, by binding; keyed off ctx, so a new incarnation starts empty. */
|
|
53
|
+
const openedInnerDoFacets = new WeakMap();
|
|
54
|
+
/**
|
|
55
|
+
* Record that this incarnation opens `facetName` for `bindingName`. True on the
|
|
56
|
+
* name's first open since the incarnation began or the binding's facets were
|
|
57
|
+
* last aborted: whatever still runs under it has a class this build no longer
|
|
58
|
+
* uses, and a get() with the new class on it resets the whole object.
|
|
59
|
+
*/
|
|
60
|
+
export function noteInnerDoFacetOpened(ctx, bindingName, facetName) {
|
|
61
|
+
let byBinding = openedInnerDoFacets.get(ctx);
|
|
62
|
+
if (!byBinding)
|
|
63
|
+
openedInnerDoFacets.set(ctx, byBinding = new Map());
|
|
64
|
+
let names = byBinding.get(bindingName);
|
|
65
|
+
if (!names)
|
|
66
|
+
byBinding.set(bindingName, names = new Set());
|
|
67
|
+
if (names.has(facetName))
|
|
68
|
+
return false;
|
|
69
|
+
names.add(facetName);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
/** Abort the facets this incarnation opened for `bindingNames`, keeping their storage, so each next request starts the class registered then. */
|
|
73
|
+
export function abortInnerDoFacets(ctx, bindingNames, reason) {
|
|
74
|
+
const byBinding = openedInnerDoFacets.get(ctx);
|
|
75
|
+
if (!byBinding)
|
|
76
|
+
return;
|
|
77
|
+
for (const bindingName of bindingNames) {
|
|
78
|
+
for (const facetName of byBinding.get(bindingName) ?? []) {
|
|
79
|
+
try {
|
|
80
|
+
ctx.facets.abort(facetName, reason);
|
|
81
|
+
}
|
|
82
|
+
catch { /* already gone */ }
|
|
83
|
+
}
|
|
84
|
+
byBinding.delete(bindingName);
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/isolate-pool.d.ts
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* 3. **Supervisor autoinjection**. The pool grabs the embedder's
|
|
16
16
|
* registered supervisor entrypoint stub (see `supervisorEntrypoint` in
|
|
17
17
|
* composition.ts) and forwards it as `env.SUPERVISOR` to every facet,
|
|
18
|
-
* same pattern as git
|
|
18
|
+
* same pattern as git/network-facet.ts. Callers can add more bindings
|
|
19
19
|
* via `extraBindings`.
|
|
20
20
|
* 4. **Fail-loud defaults**: timeout 60s, retries 0, onError 'throw'.
|
|
21
21
|
* Caller opts in to leniency.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isolate-pool.d.ts","sourceRoot":"","sources":["../src/isolate-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"isolate-pool.d.ts","sourceRoot":"","sources":["../src/isolate-pool.ts"],"names":[],"mappings":"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"}
|