@nimbus-sh/fabric 0.9.0 → 0.10.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/README.md +72 -0
- package/dist/bindings.d.ts +31 -33
- package/dist/bindings.d.ts.map +1 -1
- package/dist/bindings.js +108 -97
- package/dist/budgets.d.ts +61 -9
- package/dist/budgets.d.ts.map +1 -1
- package/dist/budgets.js +205 -31
- package/dist/fanout.d.ts.map +1 -1
- package/dist/fanout.js +4 -3
- package/dist/fenced-work.d.ts +3 -3
- package/dist/fenced-work.js +3 -3
- package/dist/inner-do-env.d.ts +83 -0
- package/dist/inner-do-env.d.ts.map +1 -0
- package/dist/inner-do-env.js +181 -0
- package/dist/isolate-pool.d.ts +9 -0
- package/dist/isolate-pool.d.ts.map +1 -1
- package/dist/isolate-pool.js +55 -27
- package/dist/workerd-facet-host.d.ts.map +1 -1
- package/dist/workerd-facet-host.js +5 -0
- package/package.json +2 -2
- package/src/bindings.ts +121 -98
- package/src/budgets.ts +244 -33
- package/src/fanout.ts +5 -3
- package/src/fenced-work.ts +3 -3
- package/src/inner-do-env.ts +213 -0
- package/src/isolate-pool.ts +65 -27
- package/src/workerd-facet-host.ts +4 -0
package/dist/isolate-pool.d.ts
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* and binding types used by this implementation.
|
|
25
25
|
*/
|
|
26
26
|
import { type HostRoute } from './composition.js';
|
|
27
|
+
import { type DynamicWorkerClaim } from './budgets.js';
|
|
27
28
|
import type { FacetBindings } from '@nimbus-sh/core/runtime/facet-host.js';
|
|
28
29
|
import type { WorkerLoader } from './vendor/types.js';
|
|
29
30
|
/**
|
|
@@ -50,6 +51,12 @@ export interface IsolatePoolOptions {
|
|
|
50
51
|
* caller that wants more sizes it against that budget (Fanout does).
|
|
51
52
|
*/
|
|
52
53
|
concurrency?: number;
|
|
54
|
+
/**
|
|
55
|
+
* The width the caller claimed for this pool's dispatches
|
|
56
|
+
* (`claimDynamicWorkers`): they are held inside it rather than on top of
|
|
57
|
+
* it, and a refused one waits for a slot of the claim.
|
|
58
|
+
*/
|
|
59
|
+
claim?: DynamicWorkerClaim;
|
|
53
60
|
/** Per-task timeout in ms. Default 60_000. */
|
|
54
61
|
timeoutMs?: number;
|
|
55
62
|
/**
|
|
@@ -254,6 +261,8 @@ export declare class IsolatePool {
|
|
|
254
261
|
private readonly loader;
|
|
255
262
|
/** The hosting actor, as the loader budget ledger's per-DO key. */
|
|
256
263
|
private readonly ctx;
|
|
264
|
+
/** The width this pool's dispatches are held inside (IsolatePoolOptions.claim). */
|
|
265
|
+
private readonly claim;
|
|
257
266
|
private readonly concurrency;
|
|
258
267
|
private readonly defaultTimeoutMs;
|
|
259
268
|
private readonly defaultRetries;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isolate-pool.d.ts","sourceRoot":"","sources":["../src/isolate-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"isolate-pool.d.ts","sourceRoot":"","sources":["../src/isolate-pool.ts"],"names":[],"mappings":"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"}
|
package/dist/isolate-pool.js
CHANGED
|
@@ -28,17 +28,18 @@ import { supervisorEntrypoint } from './composition.js';
|
|
|
28
28
|
import { supervisorBindingProps, supervisorLoaderKey } from './supervisor-props.js';
|
|
29
29
|
import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
|
|
30
30
|
import { serializeFunction, hashSource } from './vendor/serialize.js';
|
|
31
|
-
import { beginLoaderFetch, withDynamicWorkerCapNamed } from './budgets.js';
|
|
31
|
+
import { beginLoaderFetch, beginLoaderFetchWhenFree, withDynamicWorkerCapNamed, } from './budgets.js';
|
|
32
32
|
import { assertModuleMapWithinCodeLimit } from './budgets.js';
|
|
33
33
|
import { recordFailure, setLastFacetId, getLastRpcFrame } from '@nimbus-sh/platform/oom-discriminator.js';
|
|
34
34
|
import { classifyError } from '@nimbus-sh/platform/oom-classify.js';
|
|
35
35
|
import { BindingError, ExecutionError, RetryExhaustedError, TimeoutError, } from './vendor/errors.js';
|
|
36
36
|
import { hostWasmIdentity } from './host-wasm.js';
|
|
37
37
|
/**
|
|
38
|
-
* How long one call waits, in all,
|
|
39
|
-
* "Dynamic worker concurrency limit exceeded"
|
|
40
|
-
*
|
|
41
|
-
*
|
|
38
|
+
* How long one call waits, in all, on the Dynamic Worker ledger after
|
|
39
|
+
* "Dynamic worker concurrency limit exceeded" before the refusal surfaces
|
|
40
|
+
* (beginLoaderFetchWhenFree: let in when a hold ends or the refusal's pause
|
|
41
|
+
* passes). A deployed Durable Object admitted the refused batch after a 6 s
|
|
42
|
+
* pause; 15 s bounds a call that would never be admitted.
|
|
42
43
|
*/
|
|
43
44
|
const CAP_REFUSAL_WAIT_MS = 15_000;
|
|
44
45
|
/**
|
|
@@ -120,6 +121,8 @@ export class IsolatePool {
|
|
|
120
121
|
loader;
|
|
121
122
|
/** The hosting actor, as the loader budget ledger's per-DO key. */
|
|
122
123
|
ctx;
|
|
124
|
+
/** The width this pool's dispatches are held inside (IsolatePoolOptions.claim). */
|
|
125
|
+
claim;
|
|
123
126
|
concurrency;
|
|
124
127
|
defaultTimeoutMs;
|
|
125
128
|
defaultRetries;
|
|
@@ -183,6 +186,7 @@ export class IsolatePool {
|
|
|
183
186
|
}
|
|
184
187
|
this.loader = loader;
|
|
185
188
|
this.ctx = ctx;
|
|
189
|
+
this.claim = opts?.claim;
|
|
186
190
|
this.concurrency = Math.max(1, opts?.concurrency ?? 1);
|
|
187
191
|
this.defaultTimeoutMs = opts?.timeoutMs ?? 60_000;
|
|
188
192
|
this.defaultRetries = Math.max(0, opts?.retries ?? 0);
|
|
@@ -455,7 +459,7 @@ export class IsolatePool {
|
|
|
455
459
|
* the attempt index lets a fetch invoke mint a fresh clone for retries,
|
|
456
460
|
* since a Request's body is consumed once.
|
|
457
461
|
*/
|
|
458
|
-
async #dispatchSlot(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm,
|
|
462
|
+
async #dispatchSlot(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm, signal) {
|
|
459
463
|
// A warm slot executes one dispatch at a time: queue behind the
|
|
460
464
|
// previous owner, then record this dispatch as the new tail. The
|
|
461
465
|
// tail outlives the caller's outcome: a timeout rejects the
|
|
@@ -472,7 +476,7 @@ export class IsolatePool {
|
|
|
472
476
|
}
|
|
473
477
|
const inFlight = [];
|
|
474
478
|
try {
|
|
475
|
-
return await this.#dispatchSlotOwned(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm, inFlight,
|
|
479
|
+
return await this.#dispatchSlotOwned(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm, inFlight, signal);
|
|
476
480
|
}
|
|
477
481
|
finally {
|
|
478
482
|
// Do not delay the caller's own outcome — the tail releases when
|
|
@@ -480,7 +484,7 @@ export class IsolatePool {
|
|
|
480
484
|
void Promise.allSettled(inFlight).then(() => release());
|
|
481
485
|
}
|
|
482
486
|
}
|
|
483
|
-
async #dispatchSlotOwned(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm, inFlight,
|
|
487
|
+
async #dispatchSlotOwned(fnSource, fnHash, slotIndex, invoke, resilience, perCallWasm, inFlight, signal) {
|
|
484
488
|
// Per-call wasm fingerprint. Mixed into the cache key so two calls
|
|
485
489
|
// with different bytes hit different slots (no cache poisoning).
|
|
486
490
|
// For the common case (no per-call wasm) the fingerprint is '0',
|
|
@@ -502,6 +506,9 @@ export class IsolatePool {
|
|
|
502
506
|
setLastFacetId(id, slotIndex);
|
|
503
507
|
}
|
|
504
508
|
catch { /* best-effort */ }
|
|
509
|
+
// A hold the ledger already took for the next attempt, when a refused
|
|
510
|
+
// call waited on it for room; otherwise the attempt begins its own.
|
|
511
|
+
let admitted;
|
|
505
512
|
const runOnce = async () => {
|
|
506
513
|
// loader.get() is synchronous from the caller's POV; the callback
|
|
507
514
|
// is only invoked on cache miss. We wrap the callback tightly so a
|
|
@@ -527,15 +534,21 @@ export class IsolatePool {
|
|
|
527
534
|
// fine and stays — it only tears down the long-lived SUPERVISOR
|
|
528
535
|
// binding stub once the whole pool is done, which does NOT
|
|
529
536
|
// invalidate any in-flight slot's entrypoint reference.
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
//
|
|
533
|
-
|
|
534
|
-
|
|
537
|
+
//
|
|
538
|
+
// The hold comes first, so it ends whatever setup throws: a retry's
|
|
539
|
+
// was taken when the ledger let it in.
|
|
540
|
+
const endFetch = admitted ?? beginLoaderFetch(this.ctx, id, this.claim);
|
|
541
|
+
admitted = undefined;
|
|
535
542
|
try {
|
|
543
|
+
const stub = this.loader.get(id, async () => code);
|
|
544
|
+
const entrypoint = stub.getEntrypoint();
|
|
545
|
+
// Direct property call, awaited by this frame — bracketed, never
|
|
546
|
+
// wrapped. See beginLoaderFetch for the measured DO-poisoning hazard.
|
|
536
547
|
return await invoke(entrypoint, attempt);
|
|
537
548
|
}
|
|
538
549
|
catch (err) {
|
|
550
|
+
// The ledger learns a limit refusal from the hold it ends.
|
|
551
|
+
endFetch(err);
|
|
539
552
|
if (err instanceof Error) {
|
|
540
553
|
throw new ExecutionError(err.message, err.stack);
|
|
541
554
|
}
|
|
@@ -548,8 +561,8 @@ export class IsolatePool {
|
|
|
548
561
|
const maxAttempts = 1 + resilience.retries;
|
|
549
562
|
let lastError;
|
|
550
563
|
let retriedCloneRefusal = false;
|
|
551
|
-
|
|
552
|
-
let
|
|
564
|
+
// When this call's waits for room after a limit refusal run out.
|
|
565
|
+
let capDeadline;
|
|
553
566
|
let attempt = 0;
|
|
554
567
|
while (attempt < maxAttempts) {
|
|
555
568
|
try {
|
|
@@ -609,7 +622,7 @@ export class IsolatePool {
|
|
|
609
622
|
});
|
|
610
623
|
}
|
|
611
624
|
catch { /* fail-soft */ }
|
|
612
|
-
if (
|
|
625
|
+
if (signal?.aborted) {
|
|
613
626
|
// The caller aborted this dispatch's Request. workerd cancelled
|
|
614
627
|
// the isolate's execution context wherever it was suspended —
|
|
615
628
|
// mid-syscall, mid-stream — so the interpreter's heap may hold
|
|
@@ -635,16 +648,31 @@ export class IsolatePool {
|
|
|
635
648
|
// reverse direction. This refresh targets the stale-loader case.
|
|
636
649
|
continue;
|
|
637
650
|
}
|
|
638
|
-
if (cause === 'dynamic_worker_cap'
|
|
639
|
-
// The platform refused to start this call
|
|
640
|
-
//
|
|
641
|
-
//
|
|
642
|
-
//
|
|
643
|
-
//
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
651
|
+
if (cause === 'dynamic_worker_cap') {
|
|
652
|
+
// The platform refused to start this call. Nothing ran, so the
|
|
653
|
+
// call waits, as the platform asks, and is sent again without
|
|
654
|
+
// spending an attempt: on the ledger, which lets it in when a
|
|
655
|
+
// hold ends, or when the pause this refusal started has passed
|
|
656
|
+
// (the platform still counts a worker the ledger has given back:
|
|
657
|
+
// a fan-out's workers stay counted for a moment after their
|
|
658
|
+
// calls return).
|
|
659
|
+
capDeadline ??= Date.now() + CAP_REFUSAL_WAIT_MS;
|
|
660
|
+
const remainingMs = capDeadline - Date.now();
|
|
661
|
+
if (remainingMs > 0) {
|
|
662
|
+
// The deadline's timer is cleared once the wait settles: a
|
|
663
|
+
// pending timer keeps the hosting object from hibernating.
|
|
664
|
+
const deadline = new AbortController();
|
|
665
|
+
const timer = setTimeout(() => deadline.abort(), remainingMs);
|
|
666
|
+
const waitFor = signal ? AbortSignal.any([deadline.signal, signal]) : deadline.signal;
|
|
667
|
+
admitted = await beginLoaderFetchWhenFree(this.ctx, id, { claim: this.claim, signal: waitFor })
|
|
668
|
+
.catch(() => undefined)
|
|
669
|
+
.finally(() => clearTimeout(timer));
|
|
670
|
+
if (admitted)
|
|
671
|
+
continue;
|
|
672
|
+
// The caller aborted while waiting: surface its abort as above.
|
|
673
|
+
if (signal?.aborted)
|
|
674
|
+
throw lastError;
|
|
675
|
+
}
|
|
648
676
|
}
|
|
649
677
|
if (attempt < maxAttempts - 1) {
|
|
650
678
|
// 100 * 2^attempt, capped at 2s so retries don't compound waiting.
|
|
@@ -696,7 +724,7 @@ export class IsolatePool {
|
|
|
696
724
|
// Every attempt fetches a clone: a Request's body is consumed once,
|
|
697
725
|
// so the caller's original stays unspent and retries get a fresh
|
|
698
726
|
// body that follows the same signal.
|
|
699
|
-
return this.#dispatchSlot(fnSource, fnHash, 0, (entrypoint) => entrypoint.fetch(request.clone()), resilience, opts?.wasmModules,
|
|
727
|
+
return this.#dispatchSlot(fnSource, fnHash, 0, (entrypoint) => entrypoint.fetch(request.clone()), resilience, opts?.wasmModules, request.signal);
|
|
700
728
|
}
|
|
701
729
|
/**
|
|
702
730
|
* Run `fn` on every item in `items`, at most `concurrency` at a time,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workerd-facet-host.d.ts","sourceRoot":"","sources":["../src/workerd-facet-host.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"workerd-facet-host.d.ts","sourceRoot":"","sources":["../src/workerd-facet-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoBH,OAAO,EAGL,KAAK,aAAa,EAElB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AAK7B,+DAA+D;AAC/D,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5D,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE;QACjC,KAAK,EAAE;YACL,GAAG,EAAE,MAAM,CAAC;YACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,uBAAuB,CAAC;YACpC,KAAK,CAAC,EAAE,OAAO,CAAC;SACjB,CAAC;KACH,KAAK,0BAA0B,CAAC;CAClC;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CAMtD;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,gBAAgB,EAC5B,UAAU,EAAE,uBAAuB,EACnC,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,MAAM,GAAG,IAAW,GACzB,OAAO,CAAC,0BAA0B,CAAC,CAerC;AA8BD,gDAAgD;AAChD,UAAU,gBAAgB;IACxB,aAAa,IAAI,0BAA0B,CAAC;CAC7C;AAED;;;;;;;;;;;;;GAaG;AACH,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,OAAO,GAAG;QAAE,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC9F,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD,GACA,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,iEAAiE;AACjE,eAAO,MAAM,yBAAyB,cAAc,CAAC;AA4FrD,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9E;AAID;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9F;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAEnF;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADH,GAAG,EAAE,kBAAkB,EACvB,GAAG,EAAE,gBAAgB;IAGxC,8EAA8E;IAC9E,KAAK,CACH,IAAI,EAAE,MAAM,kBAAkB,EAC9B,UAAU,EAAE,uBAAuB,EACnC,MAAM,EAAE,iBAAiB,GACxB,aAAa;IAIhB;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,CAAC,EACH,UAAU,EAAE,uBAAuB,EACnC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC;CAGd;AAqPD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,MAAM,kBAAkB,EAC9B,UAAU,EAAE,uBAAuB,EACnC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAelC"}
|
|
@@ -470,6 +470,11 @@ async function runOneShot(ctx, env, supervisor, params, consume) {
|
|
|
470
470
|
disposeRpcResource(response);
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
|
+
catch (error) {
|
|
474
|
+
// A limit refusal pauses the ledger's admissions (beginLoaderFetchWhenFree).
|
|
475
|
+
endFetch(error);
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
473
478
|
finally {
|
|
474
479
|
endFetch();
|
|
475
480
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nimbus-sh/fabric",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "The Cloudflare half of Nimbus \u2014 Durable Object facet hosting, dynamic-worker loader pools, the resident-process fabric, and DO alarm/hibernation machinery.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"typecheck": "tsc --noEmit"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@nimbus-sh/core": "^0.
|
|
53
|
+
"@nimbus-sh/core": "^0.15.0",
|
|
54
54
|
"@nimbus-sh/platform": "^0.7.0",
|
|
55
55
|
"zod": "^4.4.3"
|
|
56
56
|
},
|
package/src/bindings.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { disposeRpcResource, useRpcResource } from '@nimbus-sh/platform/rpc-disp
|
|
|
29
29
|
import { hostNamespace, supervisorEntrypoint, supervisorEntrypointName, stagedBootAssembler } from './composition.js';
|
|
30
30
|
import type { HostRoute } from './composition.js';
|
|
31
31
|
import { hostNamespaceBinding, hostOpDispatch, type HostOpDispatch } from './host-dispatch.js';
|
|
32
|
+
import { innerDoIdFromName } from './inner-do-env.js';
|
|
32
33
|
import { assertModuleMapWithinCodeLimit } from './budgets.js';
|
|
33
34
|
import type { EntrypointLoopbackFactory } from './composition.js';
|
|
34
35
|
import type { WorkerCode } from './vendor/types.js';
|
|
@@ -708,46 +709,23 @@ interface NimbusDoNamespaceProps {
|
|
|
708
709
|
}
|
|
709
710
|
|
|
710
711
|
/**
|
|
711
|
-
* `env.MY_DO`
|
|
712
|
+
* The binding the loader passes for `env.MY_DO` (a WorkerEntrypoint of the
|
|
713
|
+
* session's isolate). The inner Worker does not use it as its namespace: a
|
|
714
|
+
* DurableObjectNamespace's API is synchronous, and this one's answers are
|
|
715
|
+
* RpcPromises, which cannot travel as arguments. The inner Worker replaces it
|
|
716
|
+
* with a local namespace (inner-do-env.ts, innerWorkerModules) that makes ids
|
|
717
|
+
* and stubs itself, and relays each member a stub's caller reaches, its
|
|
718
|
+
* fetch included, to `callOn` or `getOn`.
|
|
712
719
|
*
|
|
713
|
-
*
|
|
714
|
-
*
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
718
|
-
* IMPORTANT: unlike the real DurableObjectNamespace, idFromName /
|
|
719
|
-
* newUniqueId / idFromString here return **Promises**, because they're
|
|
720
|
-
* RPC-backed WorkerEntrypoint methods. The inner caller MUST `await`
|
|
721
|
-
* them before passing the result to `.get()`. Workers RPC pipelining
|
|
722
|
-
* does not currently allow passing an RpcPromise as a method argument
|
|
723
|
-
* — the no-await form fails with:
|
|
724
|
-
* "Could not serialize object of type \"RpcPromise\"."
|
|
725
|
-
*
|
|
726
|
-
* Typical real-Worker code written for Cloudflare's synchronous
|
|
727
|
-
* DurableObjectNamespace needs a one-word change (add `await`).
|
|
728
|
-
*
|
|
729
|
-
* idFromName produces prefix `name:` (deterministic FNV-style hash);
|
|
730
|
-
* newUniqueId uses `uniq:` (random). The prefixes keep the two id
|
|
731
|
-
* spaces distinct so a name-derived id can't collide with a random
|
|
732
|
-
* one.
|
|
720
|
+
* `idFromName`, `newUniqueId`, `idFromString` and `get` answer as before, for
|
|
721
|
+
* a caller that awaits them. idFromName produces prefix `name:` (a
|
|
722
|
+
* deterministic hash, innerDoIdFromName); newUniqueId uses `uniq:`; the
|
|
723
|
+
* prefixes keep the two id spaces distinct.
|
|
733
724
|
*/
|
|
734
|
-
export class NimbusDurableObjectNamespace extends WorkerEntrypoint<
|
|
725
|
+
export class NimbusDurableObjectNamespace extends WorkerEntrypoint<object, NimbusDoNamespaceProps> {
|
|
735
726
|
/** Stable string id derived from a name. Hash is deterministic. */
|
|
736
727
|
idFromName(name: string): string {
|
|
737
|
-
|
|
738
|
-
// distinct names → distinct strings; same name → same string.
|
|
739
|
-
let h1 = 0xdeadbeef ^ name.length;
|
|
740
|
-
let h2 = 0x41c6ce57 ^ name.length;
|
|
741
|
-
for (let i = 0; i < name.length; i++) {
|
|
742
|
-
const ch = name.charCodeAt(i);
|
|
743
|
-
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
744
|
-
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
745
|
-
}
|
|
746
|
-
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
747
|
-
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
748
|
-
const high = (h1 >>> 0).toString(16).padStart(8, '0');
|
|
749
|
-
const low = (h2 >>> 0).toString(16).padStart(8, '0');
|
|
750
|
-
return 'name:' + high + low;
|
|
728
|
+
return innerDoIdFromName(name);
|
|
751
729
|
}
|
|
752
730
|
|
|
753
731
|
/** Fresh random id (matches DurableObjectNamespace.newUniqueId()). */
|
|
@@ -774,6 +752,19 @@ export class NimbusDurableObjectNamespace extends WorkerEntrypoint<unknown, Nimb
|
|
|
774
752
|
},
|
|
775
753
|
});
|
|
776
754
|
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* The member of object `id` at `path` (names from the object down), called
|
|
758
|
+
* with `args`: its answer, or what it throws, as the object gave it.
|
|
759
|
+
*/
|
|
760
|
+
callOn(id: string, path: string[], args: unknown[]): Promise<unknown> {
|
|
761
|
+
return innerDoMember(this.env, { ...(this.ctx.props || {}), id: String(id) }, path, args);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/** The member of object `id` at `path`, read. */
|
|
765
|
+
getOn(id: string, path: string[]): Promise<unknown> {
|
|
766
|
+
return innerDoMember(this.env, { ...(this.ctx.props || {}), id: String(id) }, path, null);
|
|
767
|
+
}
|
|
777
768
|
}
|
|
778
769
|
|
|
779
770
|
/** Props the DO stub carries: which binding, which supervisor, which id. */
|
|
@@ -782,70 +773,102 @@ interface NimbusDoStubProps extends NimbusDoNamespaceProps {
|
|
|
782
773
|
}
|
|
783
774
|
|
|
784
775
|
/**
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
*
|
|
788
|
-
* inner DO class via getInnerDoClass() (./inner-do-registry.js) and
|
|
789
|
-
* spins up / attaches to a facet via the supervisor's ctx.facets in
|
|
790
|
-
* the SAME outer request context — never reusing stubs across requests.
|
|
776
|
+
* The session Durable Object, through the composed host namespace, and its
|
|
777
|
+
* one supervisorOp entrypoint: a host forwards envelopes, not private _rpc*
|
|
778
|
+
* methods. Throws when the binding cannot reach it; `release` drops the stub.
|
|
791
779
|
*/
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
const
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
780
|
+
function supervisorOf(env: object | undefined, props: NimbusDoStubProps): { dispatch: HostOpDispatch; release(): void } {
|
|
781
|
+
const supervisorDoId = String(props.supervisorDoId || '');
|
|
782
|
+
if (!supervisorDoId) throw new Error('supervisorDoId missing');
|
|
783
|
+
let stub: DurableObjectStub | null = null;
|
|
784
|
+
try {
|
|
785
|
+
const ns = hostNamespaceBinding(env ?? {}, 'NimbusDOStub', props.route);
|
|
786
|
+
stub = ns.get(ns.idFromString(supervisorDoId));
|
|
787
|
+
const held = stub;
|
|
788
|
+
return { dispatch: hostOpDispatch(stub, 'NimbusDOStub', props.route), release: () => disposeRpcResource(held) };
|
|
789
|
+
} catch (e) {
|
|
790
|
+
disposeRpcResource(stub);
|
|
791
|
+
throw e;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/** What the session's innerDoFetch answers: the object's response, as fields. */
|
|
796
|
+
export interface InnerDoFetchAnswer {
|
|
797
|
+
status: number;
|
|
798
|
+
statusText: string;
|
|
799
|
+
headers: [string, string][];
|
|
800
|
+
body: ArrayBuffer | null;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function isInnerDoFetchAnswer(value: unknown): value is InnerDoFetchAnswer {
|
|
804
|
+
return value !== null && typeof value === 'object'
|
|
805
|
+
&& 'status' in value && typeof value.status === 'number'
|
|
806
|
+
&& 'statusText' in value && typeof value.statusText === 'string'
|
|
807
|
+
&& 'headers' in value && Array.isArray(value.headers)
|
|
808
|
+
&& 'body' in value && (value.body === null || value.body instanceof ArrayBuffer);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* The inner object's fetch: the request forwarded whole (method, body,
|
|
813
|
+
* headers) as fields the session reconstructs, and its response rebuilt here
|
|
814
|
+
* from the fields the session answers. A binding that cannot reach the
|
|
815
|
+
* session answers 500.
|
|
816
|
+
*/
|
|
817
|
+
async function innerDoFetch(env: object | undefined, props: NimbusDoStubProps, request: Request): Promise<Response> {
|
|
818
|
+
let supervisor: ReturnType<typeof supervisorOf>;
|
|
819
|
+
try {
|
|
820
|
+
supervisor = supervisorOf(env, props);
|
|
821
|
+
} catch (e) {
|
|
822
|
+
return new Response(`Nimbus: ${e instanceof Error ? e.message : String(e)}`, { status: 500 });
|
|
823
|
+
}
|
|
824
|
+
try {
|
|
825
|
+
const body = request.method !== 'GET' && request.method !== 'HEAD' ? await request.arrayBuffer() : null;
|
|
821
826
|
const headerList: [string, string][] = [];
|
|
822
827
|
request.headers.forEach((v, k) => { headerList.push([k, v]); });
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
828
|
+
return await useRpcResource(
|
|
829
|
+
supervisor.dispatch({
|
|
830
|
+
op: 'innerDoFetch',
|
|
831
|
+
args: [{ bindingName: String(props.bindingName || ''), id: String(props.id || ''), method: request.method, url: request.url, headers: headerList, body }],
|
|
832
|
+
}),
|
|
833
|
+
(res) => {
|
|
834
|
+
if (!isInnerDoFetchAnswer(res)) {
|
|
835
|
+
return new Response('Nimbus: innerDoFetch returned an invalid result', { status: 502 });
|
|
836
|
+
}
|
|
837
|
+
return new Response(res.body, { status: res.status, statusText: res.statusText, headers: res.headers });
|
|
838
|
+
},
|
|
839
|
+
);
|
|
840
|
+
} finally {
|
|
841
|
+
supervisor.release();
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* A member of the inner object, called with `args` or read (`args` null): the
|
|
847
|
+
* session reaches it on the object's facet and answers what it answered (a
|
|
848
|
+
* stub, function or stream travels as one) or rejects with what it threw,
|
|
849
|
+
* type and message kept.
|
|
850
|
+
*/
|
|
851
|
+
async function innerDoMember(env: object | undefined, props: NimbusDoStubProps, path: string[], args: unknown[] | null): Promise<unknown> {
|
|
852
|
+
const supervisor = supervisorOf(env, props);
|
|
853
|
+
try {
|
|
854
|
+
return await supervisor.dispatch({
|
|
855
|
+
op: 'innerDoCall',
|
|
856
|
+
args: [{ bindingName: String(props.bindingName || ''), id: String(props.id || ''), path, args }],
|
|
857
|
+
});
|
|
858
|
+
} finally {
|
|
859
|
+
supervisor.release();
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* A Durable-Object-namespace-stub for a specific id, for a caller of the
|
|
865
|
+
* binding's own `get`: its fetch. The important invariant: EVERY call
|
|
866
|
+
* resolves the inner DO class via getInnerDoClass() (./inner-do-registry.js)
|
|
867
|
+
* and spins up / attaches to a facet via the supervisor's ctx.facets in the
|
|
868
|
+
* SAME outer request context — never reusing stubs across requests.
|
|
869
|
+
*/
|
|
870
|
+
export class NimbusDOStub extends WorkerEntrypoint<object, NimbusDoStubProps> {
|
|
871
|
+
async fetch(request: Request): Promise<Response> {
|
|
872
|
+
return innerDoFetch(this.env, this.ctx.props || {}, request);
|
|
850
873
|
}
|
|
851
874
|
}
|