@nimbus-sh/worker 0.2.3 → 0.4.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/_shared/session-router.d.ts +8 -0
- package/dist/_shared/session-router.d.ts.map +1 -1
- package/dist/_shared/session-router.js +8 -0
- package/dist/esbuild-wasm-bundle.generated.d.ts +1 -1
- package/dist/esbuild-wasm-bundle.generated.js +1 -1
- package/dist/facets/cirrus-real.js +1 -1
- package/dist/facets/manager.d.ts +43 -129
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +107 -318
- package/dist/facets/opencode-staging.d.ts +1 -1
- package/dist/facets/opencode-staging.d.ts.map +1 -1
- package/dist/facets/opencode-staging.js +3 -0
- package/dist/facets/real-vite-hmr.js +1 -1
- package/dist/facets/vite-dev-server.d.ts +4 -4
- package/dist/facets/vite-dev-server.js +5 -5
- package/dist/git/commands.d.ts +8 -0
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +41 -9
- package/dist/git/network-facet.d.ts +1 -1
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +39 -15
- package/dist/git-bundle.generated.d.ts +2 -2
- package/dist/git-bundle.generated.d.ts.map +1 -1
- package/dist/git-bundle.generated.js +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/loaders/child-process/spawn-facet.js +1 -1
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
- package/dist/loaders/child-process/spawn-pool.js +2 -2
- package/dist/loaders/generated-workers.d.ts +2 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +3 -3
- package/dist/loaders/npm-resolve-preamble.d.ts +3 -3
- package/dist/loaders/npm-resolve-preamble.js +3 -3
- package/dist/loaders/pre-bundle-preamble.d.ts +5 -5
- package/dist/loaders/pre-bundle-preamble.js +6 -6
- package/dist/loaders/process-host.d.ts +6 -107
- package/dist/loaders/process-host.d.ts.map +1 -1
- package/dist/loaders/process-host.js +6 -405
- package/dist/npm/install-batch-facet.d.ts +1 -1
- package/dist/npm/install-batch-facet.js +1 -1
- package/dist/npm/installer.d.ts +6 -6
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +28 -27
- package/dist/npm/pre-bundle-facet.d.ts +2 -2
- package/dist/npm/pre-bundle-facet.js +5 -5
- package/dist/npm/r2-cache.d.ts +1 -1
- package/dist/npm/resolve-facet.d.ts +1 -1
- package/dist/npm/resolve-facet.js +1 -1
- package/dist/npm/resolve-one-facet.d.ts +5 -5
- package/dist/npm/resolve-one-facet.js +5 -5
- package/dist/router/index.js +2 -2
- package/dist/router/remote-api.js +9 -1
- package/dist/runtime/bun-repl.d.ts +1 -1
- package/dist/runtime/bun-repl.js +3 -3
- package/dist/runtime/esbuild-wasm-bytes.js +1 -1
- package/dist/runtime/facet-loader-host.d.ts +5 -8
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +7 -11
- package/dist/runtime/node-repl.js +2 -2
- package/dist/runtime/node-shims-artifact.js +1 -1
- package/dist/runtime/node-shims.js +2 -1
- package/dist/runtime/opencode-artifact.js +1 -1
- package/dist/runtime/opentui-wasm-bytes.js +1 -1
- package/dist/runtime/python-repl.js +3 -3
- package/dist/runtime/ruby-repl.js +2 -2
- package/dist/runtime/ruby-resident.js +1 -1
- package/dist/runtime/sqlite-wasm-bytes.js +1 -1
- package/dist/session/diag.js +1 -1
- package/dist/session/hibernation.d.ts +20 -53
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +57 -194
- package/dist/session/init-phases.d.ts +2 -3
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +3 -2
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +8 -4
- package/dist/session/keys.d.ts +14 -37
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +18 -37
- package/dist/session/nimbus-session.d.ts +10 -15
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +28 -31
- package/dist/session/port-capability.d.ts +43 -0
- package/dist/session/port-capability.d.ts.map +1 -0
- package/dist/session/port-capability.js +49 -0
- package/dist/session/programmatic.d.ts +39 -5
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +150 -19
- package/dist/session/routes.d.ts +2 -0
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +96 -20
- package/dist/session/rpc.d.ts +36 -9
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +84 -24
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +3 -1
- package/dist/session/state-store.d.ts +3 -2
- package/dist/session/state-store.d.ts.map +1 -1
- package/dist/session/state-store.js +3 -2
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +7 -4
- package/dist/session/ws.d.ts +1 -3
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +4 -3
- package/dist/wrangler/nimbus-wrangler.js +1 -1
- package/package.json +4 -2
- package/scripts/bundle-esbuild-wasm.mjs +2 -2
- package/scripts/bundle-facet-workers.mjs +5 -7
- package/scripts/bundle-sqlite-wasm.mjs +1 -1
- package/dist/facets/inner-do-registry.d.ts +0 -41
- package/dist/facets/inner-do-registry.d.ts.map +0 -1
- package/dist/facets/inner-do-registry.js +0 -51
- package/dist/facets/launch-pacer.d.ts +0 -111
- package/dist/facets/launch-pacer.d.ts.map +0 -1
- package/dist/facets/launch-pacer.js +0 -130
- package/dist/loaders/fanout-pool.d.ts +0 -207
- package/dist/loaders/fanout-pool.d.ts.map +0 -1
- package/dist/loaders/fanout-pool.js +0 -363
- package/dist/loaders/loader-pool.d.ts +0 -294
- package/dist/loaders/loader-pool.d.ts.map +0 -1
- package/dist/loaders/loader-pool.js +0 -642
- package/dist/loaders/process-fabric.d.ts +0 -509
- package/dist/loaders/process-fabric.d.ts.map +0 -1
- package/dist/loaders/process-fabric.js +0 -360
- package/dist/loaders/vendor/errors.d.ts +0 -24
- package/dist/loaders/vendor/errors.d.ts.map +0 -1
- package/dist/loaders/vendor/errors.js +0 -46
- package/dist/loaders/vendor/serialize.d.ts +0 -3
- package/dist/loaders/vendor/serialize.d.ts.map +0 -1
- package/dist/loaders/vendor/serialize.js +0 -25
- package/dist/loaders/vendor/types.d.ts +0 -69
- package/dist/loaders/vendor/types.d.ts.map +0 -1
- package/dist/loaders/vendor/types.js +0 -4
- package/dist/loaders/workerd-facet-host.d.ts +0 -141
- package/dist/loaders/workerd-facet-host.d.ts.map +0 -1
- package/dist/loaders/workerd-facet-host.js +0 -284
- package/dist/session/bindings.d.ts +0 -209
- package/dist/session/bindings.d.ts.map +0 -1
- package/dist/session/bindings.js +0 -680
- package/dist/session/ctx-exports.d.ts +0 -16
- package/dist/session/ctx-exports.d.ts.map +0 -1
- package/dist/session/ctx-exports.js +0 -22
- package/dist/session/ws-hibernation-config.d.ts +0 -64
- package/dist/session/ws-hibernation-config.d.ts.map +0 -1
- package/dist/session/ws-hibernation-config.js +0 -89
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Why this exists
|
|
6
6
|
* ───────────────
|
|
7
7
|
* Pre-bundling npm packages (the `Pre-bundling N modules…` step in
|
|
8
|
-
* src/npm/installer.ts) runs inside
|
|
8
|
+
* src/npm/installer.ts) runs inside NimbusIsolatePool isolates so each
|
|
9
9
|
* `esbuild.build()` allocation hits a fresh 128 MiB envelope rather
|
|
10
10
|
* than the supervisor's. The facet needs two pieces of esbuild-wasm
|
|
11
11
|
* at module-load time:
|
|
@@ -175,7 +175,7 @@ async function main() {
|
|
|
175
175
|
* esbuild-wasm-bundle.generated.ts — AUTO-GENERATED by scripts/bundle-esbuild-wasm.mjs
|
|
176
176
|
* DO NOT EDIT.
|
|
177
177
|
*
|
|
178
|
-
* Bundled esbuild-wasm ${version} adapter for use inside
|
|
178
|
+
* Bundled esbuild-wasm ${version} adapter for use inside NimbusIsolatePool
|
|
179
179
|
* isolates. Only the JS adapter is bundled here (~117 KiB); the wasm
|
|
180
180
|
* binary itself lives in the static-assets layer at
|
|
181
181
|
* public/_assets/esbuild-${version}.wasm and is fetched on demand by
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* injects into dynamic workers.
|
|
5
5
|
*
|
|
6
6
|
* WHY this exists:
|
|
7
|
-
* Dynamic workers (NimbusFacetPool /
|
|
7
|
+
* Dynamic workers (NimbusFacetPool / NimbusIsolatePool) receive their
|
|
8
8
|
* module source as strings — they cannot import supervisor modules,
|
|
9
9
|
* and user functions cannot capture supervisor closure variables. Any
|
|
10
10
|
* TypeScript the injected code needs must therefore be esbuild-bundled
|
|
@@ -51,6 +51,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
51
51
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
52
52
|
const root = join(__dirname, '..');
|
|
53
53
|
const coreRoot = join(root, '..', 'core');
|
|
54
|
+
const platformRoot = join(root, '..', 'platform');
|
|
54
55
|
|
|
55
56
|
/**
|
|
56
57
|
* Bundle one TS source into a self-contained ESM string suitable for
|
|
@@ -273,11 +274,8 @@ async function main() {
|
|
|
273
274
|
// facet has no access to the encoder symbol (cloudflare-parallel
|
|
274
275
|
// serialises via fn.toString() — no runtime imports).
|
|
275
276
|
//
|
|
276
|
-
// The W7-frame module imports a TypeScript type from sqlite-vfs,
|
|
277
|
-
// which esbuild's type-stripping handles transparently. The
|
|
278
|
-
// runtime output has no imports.
|
|
279
277
|
const w7Stripped = await bundleAsPreamble(
|
|
280
|
-
join(
|
|
278
|
+
join(platformRoot, 'src', 'w7-frame.ts'),
|
|
281
279
|
'w7-frame',
|
|
282
280
|
);
|
|
283
281
|
|
|
@@ -291,7 +289,7 @@ async function main() {
|
|
|
291
289
|
' *',
|
|
292
290
|
' * Produced by scripts/bundle-facet-workers.mjs from:',
|
|
293
291
|
' * - @nimbus-sh/core src/_shared/tarball-stream.ts (streaming tar primitives)',
|
|
294
|
-
' * - @nimbus-sh/
|
|
292
|
+
' * - @nimbus-sh/platform src/w7-frame.ts (W7 streaming bulk-write encoder)',
|
|
295
293
|
' *',
|
|
296
294
|
' * Consumed by src/loaders/loader-pool.ts callers via the `preamble`',
|
|
297
295
|
' * option. The preamble is injected at the top of every generated',
|
|
@@ -327,7 +325,7 @@ async function main() {
|
|
|
327
325
|
' *',
|
|
328
326
|
' * Self-contained IIFE that installs globalThis.__nimbusVirtualSockets.',
|
|
329
327
|
' * Consumed by python-runner.ts and ruby-runner.ts: spliced into the',
|
|
330
|
-
' * socket process worker module source passed to
|
|
328
|
+
' * socket process worker module source passed to NimbusIsolatePool.',
|
|
331
329
|
' *',
|
|
332
330
|
` * Size: ${(kernelSrc.length / 1024).toFixed(2)} KiB`,
|
|
333
331
|
' */',
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Why this exists
|
|
7
7
|
* ───────────────
|
|
8
|
-
* `import { DatabaseSync } from "node:sqlite"` runs inside
|
|
8
|
+
* `import { DatabaseSync } from "node:sqlite"` runs inside NimbusIsolatePool
|
|
9
9
|
* facet isolates. sql.js (Emscripten SQLite) needs two pieces at facet
|
|
10
10
|
* runtime:
|
|
11
11
|
*
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* inner-do-registry.ts — Module-level registry of inner DO classes.
|
|
3
|
-
*
|
|
4
|
-
* `nimbus-wrangler` populates this on each successful buildAndLoad()
|
|
5
|
-
* with the DurableObject classes extracted from the freshly-loaded
|
|
6
|
-
* inner Worker via `worker.getDurableObjectClass(name)`. The supervisor
|
|
7
|
-
* DO (`NimbusSession`) reads it on each inner-DO fetch to synthesize a
|
|
8
|
-
* NimbusDurableObjectNamespace stub for `env.MY_DO`.
|
|
9
|
-
*
|
|
10
|
-
* Why a separate leaf module:
|
|
11
|
-
* Before this extraction, the registry lived inside nimbus-session.ts,
|
|
12
|
-
* which forced nimbus-wrangler.ts to import from nimbus-session.ts —
|
|
13
|
-
* producing the cycle
|
|
14
|
-
* index.ts -> nimbus-session.ts -> nimbus-wrangler.ts -> nimbus-session.ts
|
|
15
|
-
* Promoting the registry to its own leaf breaks that cycle without
|
|
16
|
-
* changing any semantics. The Map identity is preserved across the
|
|
17
|
-
* isolate (it's still process-scoped — module-level state — survives
|
|
18
|
-
* across DO instances in the same workerd process).
|
|
19
|
-
*
|
|
20
|
-
* Key shape:
|
|
21
|
-
* `<supervisor-DO-id>:<binding-name>` — both halves are required to
|
|
22
|
-
* prevent multiple supervisor DOs in the same isolate from clobbering
|
|
23
|
-
* each other's registrations.
|
|
24
|
-
*
|
|
25
|
-
* The values are DurableObject class constructors. `any` here is
|
|
26
|
-
* deliberate: the inner DO's class shape is whatever the user defines
|
|
27
|
-
* in their inner Worker, and we only need to invoke it via
|
|
28
|
-
* `ctx.facets.get(name, { class: cls, id })` — workerd does the rest.
|
|
29
|
-
*/
|
|
30
|
-
/** Look up a registered inner-DO class. Returns undefined if not found. */
|
|
31
|
-
export declare function getInnerDoClass(supervisorDoId: string, bindingName: string): any | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* Register an inner DO class for synthesis. Called by nimbus-wrangler.ts
|
|
34
|
-
* after each successful buildAndLoad() with the class extracted from
|
|
35
|
-
* the fresh worker stub. Keys are `<doId>:<bindingName>` so multiple
|
|
36
|
-
* supervisor DOs don't collide.
|
|
37
|
-
*/
|
|
38
|
-
export declare function registerInnerDoClass(supervisorDoId: string, bindingName: string, cls: any): void;
|
|
39
|
-
/** Clear all registrations belonging to a supervisor DO (called on rebuild). */
|
|
40
|
-
export declare function clearInnerDoClasses(supervisorDoId: string): void;
|
|
41
|
-
//# sourceMappingURL=inner-do-registry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inner-do-registry.d.ts","sourceRoot":"","sources":["../../src/facets/inner-do-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAE5F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,GAAG,GACP,IAAI,CAEN;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAKhE"}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* inner-do-registry.ts — Module-level registry of inner DO classes.
|
|
3
|
-
*
|
|
4
|
-
* `nimbus-wrangler` populates this on each successful buildAndLoad()
|
|
5
|
-
* with the DurableObject classes extracted from the freshly-loaded
|
|
6
|
-
* inner Worker via `worker.getDurableObjectClass(name)`. The supervisor
|
|
7
|
-
* DO (`NimbusSession`) reads it on each inner-DO fetch to synthesize a
|
|
8
|
-
* NimbusDurableObjectNamespace stub for `env.MY_DO`.
|
|
9
|
-
*
|
|
10
|
-
* Why a separate leaf module:
|
|
11
|
-
* Before this extraction, the registry lived inside nimbus-session.ts,
|
|
12
|
-
* which forced nimbus-wrangler.ts to import from nimbus-session.ts —
|
|
13
|
-
* producing the cycle
|
|
14
|
-
* index.ts -> nimbus-session.ts -> nimbus-wrangler.ts -> nimbus-session.ts
|
|
15
|
-
* Promoting the registry to its own leaf breaks that cycle without
|
|
16
|
-
* changing any semantics. The Map identity is preserved across the
|
|
17
|
-
* isolate (it's still process-scoped — module-level state — survives
|
|
18
|
-
* across DO instances in the same workerd process).
|
|
19
|
-
*
|
|
20
|
-
* Key shape:
|
|
21
|
-
* `<supervisor-DO-id>:<binding-name>` — both halves are required to
|
|
22
|
-
* prevent multiple supervisor DOs in the same isolate from clobbering
|
|
23
|
-
* each other's registrations.
|
|
24
|
-
*
|
|
25
|
-
* The values are DurableObject class constructors. `any` here is
|
|
26
|
-
* deliberate: the inner DO's class shape is whatever the user defines
|
|
27
|
-
* in their inner Worker, and we only need to invoke it via
|
|
28
|
-
* `ctx.facets.get(name, { class: cls, id })` — workerd does the rest.
|
|
29
|
-
*/
|
|
30
|
-
const _NIMBUS_INNER_DO_CLASSES = new Map();
|
|
31
|
-
/** Look up a registered inner-DO class. Returns undefined if not found. */
|
|
32
|
-
export function getInnerDoClass(supervisorDoId, bindingName) {
|
|
33
|
-
return _NIMBUS_INNER_DO_CLASSES.get(supervisorDoId + ':' + bindingName);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Register an inner DO class for synthesis. Called by nimbus-wrangler.ts
|
|
37
|
-
* after each successful buildAndLoad() with the class extracted from
|
|
38
|
-
* the fresh worker stub. Keys are `<doId>:<bindingName>` so multiple
|
|
39
|
-
* supervisor DOs don't collide.
|
|
40
|
-
*/
|
|
41
|
-
export function registerInnerDoClass(supervisorDoId, bindingName, cls) {
|
|
42
|
-
_NIMBUS_INNER_DO_CLASSES.set(supervisorDoId + ':' + bindingName, cls);
|
|
43
|
-
}
|
|
44
|
-
/** Clear all registrations belonging to a supervisor DO (called on rebuild). */
|
|
45
|
-
export function clearInnerDoClasses(supervisorDoId) {
|
|
46
|
-
const prefix = supervisorDoId + ':';
|
|
47
|
-
for (const k of _NIMBUS_INNER_DO_CLASSES.keys()) {
|
|
48
|
-
if (k.startsWith(prefix))
|
|
49
|
-
_NIMBUS_INNER_DO_CLASSES.delete(k);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* launch-pacer.ts — spreading a resident launch across Durable Object turns.
|
|
3
|
-
*
|
|
4
|
-
* Building a resident process is the largest single span of computation this
|
|
5
|
-
* session performs: for pi it walks a 17 MB source tree through eight
|
|
6
|
-
* enrichment passes, serializes a 22.9 MB module map, and writes that map into
|
|
7
|
-
* the image store. Done in one turn it occupied the session DO's only thread
|
|
8
|
-
* for 15-35 s, and a session that cannot reach its thread cannot service the
|
|
9
|
-
* terminal WebSocket — the launch turn finished `outcome=ok` and the terminal
|
|
10
|
-
* died anyway, painting "[process terminal closed]" over a process that was
|
|
11
|
-
* still running.
|
|
12
|
-
*
|
|
13
|
-
* A faster launch does not fix that. A launch half the length still blocks the
|
|
14
|
-
* thread for as long as it runs, and the socket is dropped inside that window
|
|
15
|
-
* whether or not the work succeeds. What fixes it is never holding the thread
|
|
16
|
-
* for long in the first place, which means suspending the launch at bounded
|
|
17
|
-
* intervals and resuming it on a fresh turn. Responsiveness stops depending on
|
|
18
|
-
* how long the total work takes.
|
|
19
|
-
*
|
|
20
|
-
* A fresh turn is also a fresh CPU budget. The same launches that dropped the
|
|
21
|
-
* socket were also being killed with `exceededCpu` at 31.8 s and 32.5 s
|
|
22
|
-
* against a 30 s ceiling, and no amount of yielding *within* one invocation
|
|
23
|
-
* moves that: CPU accrues to the invocation, not to the pause. Only genuinely
|
|
24
|
-
* re-entering the object resets it.
|
|
25
|
-
*
|
|
26
|
-
* Progress is measured in bytes rather than milliseconds because workerd's
|
|
27
|
-
* clock does not advance without I/O — a wall-clock guard inside a span of
|
|
28
|
-
* pure computation reads zero however many seconds it burns, which is why the
|
|
29
|
-
* phase costs behind this module had to be recovered from per-turn `cpuTime`
|
|
30
|
-
* rather than measured in place. Bytes are what the work is actually
|
|
31
|
-
* proportional to, and they are exact. The same reasoning is why
|
|
32
|
-
* `git/network-facet.ts` bounds its checkout chunks by entries and decoded
|
|
33
|
-
* bytes and treats its wall guard as coarse.
|
|
34
|
-
*/
|
|
35
|
-
/** How a paced launch gets back onto a fresh Durable Object turn. */
|
|
36
|
-
export interface LaunchTurnScheduler {
|
|
37
|
-
/**
|
|
38
|
-
* Suspend until a fresh turn is running this launch again.
|
|
39
|
-
*
|
|
40
|
-
* `chunkEnded` settles when the resumed launch reaches its next suspension
|
|
41
|
-
* point or finishes, so whoever grants the turn can await the work it just
|
|
42
|
-
* released rather than letting it run detached in a handler's microtask
|
|
43
|
-
* drain.
|
|
44
|
-
*/
|
|
45
|
-
nextTurn(chunkEnded: Promise<void>): Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Bytes of launch work one turn may perform before it must yield.
|
|
49
|
-
*
|
|
50
|
-
* Sized so a chunk stays far below both the CPU ceiling and the span in which
|
|
51
|
-
* a terminal socket is at risk, while keeping the number of turn handoffs —
|
|
52
|
-
* each an alarm round trip — small enough not to dominate a launch. pi's
|
|
53
|
-
* 22.9 MB map crosses this about a dozen times per phase that handles it.
|
|
54
|
-
*/
|
|
55
|
-
export declare const LAUNCH_CHUNK_MAX_BYTES = 2000000;
|
|
56
|
-
/**
|
|
57
|
-
* Accounts launch progress and ends the turn when a chunk's worth has been
|
|
58
|
-
* spent.
|
|
59
|
-
*
|
|
60
|
-
* Callers report the work they are about to do or have just done and await
|
|
61
|
-
* the result; a pacer that is not yielding returns without suspending, so the
|
|
62
|
-
* one-shot exec path — which passes no pacer at all — keeps its exact
|
|
63
|
-
* behaviour and cost. Nothing here decides WHAT the launch does, only where it
|
|
64
|
-
* is allowed to stop.
|
|
65
|
-
*/
|
|
66
|
-
export declare class LaunchPacer {
|
|
67
|
-
private readonly scheduler;
|
|
68
|
-
private readonly maxChunkBytes;
|
|
69
|
-
private readonly stillWanted?;
|
|
70
|
-
/** Turn handoffs this launch has taken. Reported with the launch. */
|
|
71
|
-
chunks: number;
|
|
72
|
-
/** Total work accounted, for the same report. */
|
|
73
|
-
bytes: number;
|
|
74
|
-
private spent;
|
|
75
|
-
private chunkEnded;
|
|
76
|
-
/**
|
|
77
|
-
* @param stillWanted Checked every time the launch resumes. A launch spans
|
|
78
|
-
* many turns, so anything may have happened to what it is building for
|
|
79
|
-
* while it was suspended; throwing from here is how a launch stops instead
|
|
80
|
-
* of spending turn after turn on work nothing will use. Checked at the one
|
|
81
|
-
* place a launch can be interrupted, rather than at whichever phases
|
|
82
|
-
* remembered to ask.
|
|
83
|
-
*/
|
|
84
|
-
constructor(scheduler: LaunchTurnScheduler, maxChunkBytes?: number, stillWanted?: (() => void) | undefined);
|
|
85
|
-
/**
|
|
86
|
-
* Account `bytes` of completed work, ending the turn if a chunk is full.
|
|
87
|
-
*
|
|
88
|
-
* Safe to call anywhere the launch holds no state that a concurrent turn
|
|
89
|
-
* could invalidate — which is why the image store registers its whole root
|
|
90
|
-
* set before the first call rather than one entry at a time.
|
|
91
|
-
*/
|
|
92
|
-
spend(bytes: number): Promise<void>;
|
|
93
|
-
/**
|
|
94
|
-
* The launch has finished (or failed). Releases the turn still waiting on
|
|
95
|
-
* the chunk it resumed, so a launch that ends mid-chunk does not strand the
|
|
96
|
-
* handler that granted it.
|
|
97
|
-
*/
|
|
98
|
-
settle(): void;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Chunk bound for this session, honouring the verification knob.
|
|
102
|
-
*
|
|
103
|
-
* `NIMBUS_LAUNCH_CHUNK_BYTES` forces a small bound so an ordinary launch —
|
|
104
|
-
* not just a pathological one — crosses several turns and exercises every
|
|
105
|
-
* suspension point. Without it the multi-turn path would only ever be
|
|
106
|
-
* reached by the largest programs, which is the same reason
|
|
107
|
-
* `git/commands.ts` carries `NIMBUS_GIT_CHECKOUT_CHUNK_ENTRIES`. Unset in
|
|
108
|
-
* production, where the default applies.
|
|
109
|
-
*/
|
|
110
|
-
export declare function launchChunkMaxBytes(env: unknown): number;
|
|
111
|
-
//# sourceMappingURL=launch-pacer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"launch-pacer.d.ts","sourceRoot":"","sources":["../../src/facets/launch-pacer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IAClC;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAEhD;;;;;;;;;GASG;AACH,qBAAa,WAAW;IAkBpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAnB/B,qEAAqE;IACrE,MAAM,SAAK;IACX,iDAAiD;IACjD,KAAK,SAAK;IAEV,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,UAAU,CAA8D;IAEhF;;;;;;;OAOG;gBAEgB,SAAS,EAAE,mBAAmB,EAC9B,aAAa,GAAE,MAA+B,EAC9C,WAAW,CAAC,GAAE,MAAM,IAAI,aAAA;IAG3C;;;;;;OAMG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAczC;;;;OAIG;IACH,MAAM,IAAI,IAAI;CAIf;AAQD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMxD"}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* launch-pacer.ts — spreading a resident launch across Durable Object turns.
|
|
3
|
-
*
|
|
4
|
-
* Building a resident process is the largest single span of computation this
|
|
5
|
-
* session performs: for pi it walks a 17 MB source tree through eight
|
|
6
|
-
* enrichment passes, serializes a 22.9 MB module map, and writes that map into
|
|
7
|
-
* the image store. Done in one turn it occupied the session DO's only thread
|
|
8
|
-
* for 15-35 s, and a session that cannot reach its thread cannot service the
|
|
9
|
-
* terminal WebSocket — the launch turn finished `outcome=ok` and the terminal
|
|
10
|
-
* died anyway, painting "[process terminal closed]" over a process that was
|
|
11
|
-
* still running.
|
|
12
|
-
*
|
|
13
|
-
* A faster launch does not fix that. A launch half the length still blocks the
|
|
14
|
-
* thread for as long as it runs, and the socket is dropped inside that window
|
|
15
|
-
* whether or not the work succeeds. What fixes it is never holding the thread
|
|
16
|
-
* for long in the first place, which means suspending the launch at bounded
|
|
17
|
-
* intervals and resuming it on a fresh turn. Responsiveness stops depending on
|
|
18
|
-
* how long the total work takes.
|
|
19
|
-
*
|
|
20
|
-
* A fresh turn is also a fresh CPU budget. The same launches that dropped the
|
|
21
|
-
* socket were also being killed with `exceededCpu` at 31.8 s and 32.5 s
|
|
22
|
-
* against a 30 s ceiling, and no amount of yielding *within* one invocation
|
|
23
|
-
* moves that: CPU accrues to the invocation, not to the pause. Only genuinely
|
|
24
|
-
* re-entering the object resets it.
|
|
25
|
-
*
|
|
26
|
-
* Progress is measured in bytes rather than milliseconds because workerd's
|
|
27
|
-
* clock does not advance without I/O — a wall-clock guard inside a span of
|
|
28
|
-
* pure computation reads zero however many seconds it burns, which is why the
|
|
29
|
-
* phase costs behind this module had to be recovered from per-turn `cpuTime`
|
|
30
|
-
* rather than measured in place. Bytes are what the work is actually
|
|
31
|
-
* proportional to, and they are exact. The same reasoning is why
|
|
32
|
-
* `git/network-facet.ts` bounds its checkout chunks by entries and decoded
|
|
33
|
-
* bytes and treats its wall guard as coarse.
|
|
34
|
-
*/
|
|
35
|
-
/**
|
|
36
|
-
* Bytes of launch work one turn may perform before it must yield.
|
|
37
|
-
*
|
|
38
|
-
* Sized so a chunk stays far below both the CPU ceiling and the span in which
|
|
39
|
-
* a terminal socket is at risk, while keeping the number of turn handoffs —
|
|
40
|
-
* each an alarm round trip — small enough not to dominate a launch. pi's
|
|
41
|
-
* 22.9 MB map crosses this about a dozen times per phase that handles it.
|
|
42
|
-
*/
|
|
43
|
-
export const LAUNCH_CHUNK_MAX_BYTES = 2_000_000;
|
|
44
|
-
/**
|
|
45
|
-
* Accounts launch progress and ends the turn when a chunk's worth has been
|
|
46
|
-
* spent.
|
|
47
|
-
*
|
|
48
|
-
* Callers report the work they are about to do or have just done and await
|
|
49
|
-
* the result; a pacer that is not yielding returns without suspending, so the
|
|
50
|
-
* one-shot exec path — which passes no pacer at all — keeps its exact
|
|
51
|
-
* behaviour and cost. Nothing here decides WHAT the launch does, only where it
|
|
52
|
-
* is allowed to stop.
|
|
53
|
-
*/
|
|
54
|
-
export class LaunchPacer {
|
|
55
|
-
scheduler;
|
|
56
|
-
maxChunkBytes;
|
|
57
|
-
stillWanted;
|
|
58
|
-
/** Turn handoffs this launch has taken. Reported with the launch. */
|
|
59
|
-
chunks = 0;
|
|
60
|
-
/** Total work accounted, for the same report. */
|
|
61
|
-
bytes = 0;
|
|
62
|
-
spent = 0;
|
|
63
|
-
chunkEnded;
|
|
64
|
-
/**
|
|
65
|
-
* @param stillWanted Checked every time the launch resumes. A launch spans
|
|
66
|
-
* many turns, so anything may have happened to what it is building for
|
|
67
|
-
* while it was suspended; throwing from here is how a launch stops instead
|
|
68
|
-
* of spending turn after turn on work nothing will use. Checked at the one
|
|
69
|
-
* place a launch can be interrupted, rather than at whichever phases
|
|
70
|
-
* remembered to ask.
|
|
71
|
-
*/
|
|
72
|
-
constructor(scheduler, maxChunkBytes = LAUNCH_CHUNK_MAX_BYTES, stillWanted) {
|
|
73
|
-
this.scheduler = scheduler;
|
|
74
|
-
this.maxChunkBytes = maxChunkBytes;
|
|
75
|
-
this.stillWanted = stillWanted;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Account `bytes` of completed work, ending the turn if a chunk is full.
|
|
79
|
-
*
|
|
80
|
-
* Safe to call anywhere the launch holds no state that a concurrent turn
|
|
81
|
-
* could invalidate — which is why the image store registers its whole root
|
|
82
|
-
* set before the first call rather than one entry at a time.
|
|
83
|
-
*/
|
|
84
|
-
async spend(bytes) {
|
|
85
|
-
this.bytes += bytes;
|
|
86
|
-
this.spent += bytes;
|
|
87
|
-
if (this.spent < this.maxChunkBytes)
|
|
88
|
-
return;
|
|
89
|
-
this.spent = 0;
|
|
90
|
-
this.chunks++;
|
|
91
|
-
// Release the turn that resumed us before asking for the next one.
|
|
92
|
-
this.chunkEnded?.resolve();
|
|
93
|
-
const ended = withResolvers();
|
|
94
|
-
this.chunkEnded = ended;
|
|
95
|
-
await this.scheduler.nextTurn(ended.promise);
|
|
96
|
-
this.stillWanted?.();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* The launch has finished (or failed). Releases the turn still waiting on
|
|
100
|
-
* the chunk it resumed, so a launch that ends mid-chunk does not strand the
|
|
101
|
-
* handler that granted it.
|
|
102
|
-
*/
|
|
103
|
-
settle() {
|
|
104
|
-
this.chunkEnded?.resolve();
|
|
105
|
-
this.chunkEnded = undefined;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function withResolvers() {
|
|
109
|
-
let resolve;
|
|
110
|
-
const promise = new Promise((r) => { resolve = r; });
|
|
111
|
-
return { promise, resolve };
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Chunk bound for this session, honouring the verification knob.
|
|
115
|
-
*
|
|
116
|
-
* `NIMBUS_LAUNCH_CHUNK_BYTES` forces a small bound so an ordinary launch —
|
|
117
|
-
* not just a pathological one — crosses several turns and exercises every
|
|
118
|
-
* suspension point. Without it the multi-turn path would only ever be
|
|
119
|
-
* reached by the largest programs, which is the same reason
|
|
120
|
-
* `git/commands.ts` carries `NIMBUS_GIT_CHECKOUT_CHUNK_ENTRIES`. Unset in
|
|
121
|
-
* production, where the default applies.
|
|
122
|
-
*/
|
|
123
|
-
export function launchChunkMaxBytes(env) {
|
|
124
|
-
const raw = env
|
|
125
|
-
?.NIMBUS_LAUNCH_CHUNK_BYTES;
|
|
126
|
-
if (!raw)
|
|
127
|
-
return LAUNCH_CHUNK_MAX_BYTES;
|
|
128
|
-
const parsed = Number(raw);
|
|
129
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : LAUNCH_CHUNK_MAX_BYTES;
|
|
130
|
-
}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Two-tier fan-out primitive for work that must execute in Worker Loader
|
|
3
|
-
* facets without tripping workerd's per-DO dynamic-worker ceiling.
|
|
4
|
-
*
|
|
5
|
-
* A single Durable Object method can drive at most four concurrent
|
|
6
|
-
* Worker Loader fetches before extra dispatches serialize or fail. Small
|
|
7
|
-
* batches therefore run in the coordinator DO through NimbusLoaderPool.
|
|
8
|
-
* Wider batches are sharded across sibling NimbusSession DOs, each of
|
|
9
|
-
* which owns its own four-loader budget.
|
|
10
|
-
*
|
|
11
|
-
* Routing is deterministic: each task has a stable key, and the key maps
|
|
12
|
-
* to a sibling DO shard. There is no silent fallback to width-1 execution;
|
|
13
|
-
* missing LOADER or NIMBUS_SESSION bindings fail loudly so install and
|
|
14
|
-
* runtime operations do not appear successful after partial dispatch.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* Threshold at which routing switches from coordinator-local loaders to
|
|
18
|
-
* sibling Durable Objects.
|
|
19
|
-
*
|
|
20
|
-
* Set to **5** so the in-DO path stays below the V8 4-loaders-per-method
|
|
21
|
-
* cap by construction. width < 5 stays local; width >= 5 uses sibling DOs.
|
|
22
|
-
*/
|
|
23
|
-
export declare const IN_DO_THRESHOLD = 5;
|
|
24
|
-
/**
|
|
25
|
-
* Hard cap on concurrent peer DOs per single submitMany call. Throughput stays
|
|
26
|
-
* flat through this width while keeping per-request scheduler pressure bounded.
|
|
27
|
-
*/
|
|
28
|
-
export declare const MAX_PEER_FANOUT = 32;
|
|
29
|
-
/**
|
|
30
|
-
* Bounded retries for a peer-DO shard dispatch that rejects with a
|
|
31
|
-
* transient platform reset (code roll-over, storage cold-start hiccup).
|
|
32
|
-
* Sibling DOs are addressed by stable name, so the retry re-dispatches
|
|
33
|
-
* the SAME shard to the re-provisioning object; the fanned-out work
|
|
34
|
-
* (packument resolution, tarball materialisation) is idempotent, so
|
|
35
|
-
* re-running a shard is safe. Budget mirrors the resolve-facet's own
|
|
36
|
-
* per-fetch retry policy so a single flaky cold start no longer fails a
|
|
37
|
-
* whole install. The same budget covers an overloaded peer, on the longer
|
|
38
|
-
* schedule below. Non-transient rejections (OOM, count mismatch, genuine
|
|
39
|
-
* task throw) are NOT retried — they propagate on the first hit.
|
|
40
|
-
*/
|
|
41
|
-
export declare const PEER_TRANSIENT_RESET_RETRIES = 3;
|
|
42
|
-
export declare const PEER_RETRY_BACKOFF_MS: number[];
|
|
43
|
-
/**
|
|
44
|
-
* Backoff for a shard whose peer DO was shed as overloaded. The object is
|
|
45
|
-
* alive and the shard never ran; what it needs is time for the input-gate
|
|
46
|
-
* queue to drain, so the schedule is an order of magnitude longer than the
|
|
47
|
-
* reset schedule. A whole-batch abort here used to fail an entire install.
|
|
48
|
-
*/
|
|
49
|
-
export declare const PEER_OVERLOAD_BACKOFF_MS: number[];
|
|
50
|
-
/**
|
|
51
|
-
* Peer shards dispatched per phase. Each phase is a barrier that costs its
|
|
52
|
-
* slowest member, so a wide fan-out pays ⌈shards / FANOUT_PHASE_SIZE⌉ serial
|
|
53
|
-
* round-trips; the size trades that serialization against simultaneous cold
|
|
54
|
-
* sibling DO starts.
|
|
55
|
-
*
|
|
56
|
-
* The six-barrier profile once measured on a 123-package install (21 shards of
|
|
57
|
-
* ~6 packages, 10.6/6.8/21.8/7.9/34.6/4.8 s) came from the shard count, not
|
|
58
|
-
* from this width. Capping install shards at INSTALL_PEER_CAP fixed it at the
|
|
59
|
-
* source and that install now clears in two phases. Widening to 8 on top of
|
|
60
|
-
* that bought one further barrier and doubled the simultaneous cold sibling-DO
|
|
61
|
-
* starts, which is the account-level pressure the phasing exists for: twelve
|
|
62
|
-
* concurrent Markflow installs went from 48 simultaneous peer starts to 96 and
|
|
63
|
-
* began timing out. Phasing does not change how many peers start, only how
|
|
64
|
-
* many start at once, so this width is set by the burst the scheduler
|
|
65
|
-
* tolerates rather than by the barrier count.
|
|
66
|
-
*/
|
|
67
|
-
export declare const FANOUT_PHASE_SIZE = 4;
|
|
68
|
-
/** Argument shape for `submitMany`. */
|
|
69
|
-
export interface FanoutTask<A> {
|
|
70
|
-
/**
|
|
71
|
-
* Routing key for the stable-id router. Same key → same peer DO
|
|
72
|
-
* (when on the peer-DO path). Tests use this to predict placement.
|
|
73
|
-
*/
|
|
74
|
-
key: string;
|
|
75
|
-
/** Argument passed to the user fn. */
|
|
76
|
-
args: A;
|
|
77
|
-
}
|
|
78
|
-
/** Options handed to NimbusFanoutPool's constructor. */
|
|
79
|
-
export interface NimbusFanoutPoolOptions {
|
|
80
|
-
/**
|
|
81
|
-
* Tag prepended to peer-DO ids and in-DO loader ids for debugging
|
|
82
|
-
* (e.g. "npm-install-batch"). Affects neither isolate identity (in-DO
|
|
83
|
-
* path uses the existing NimbusLoaderPool's tag-fold) nor peer-DO
|
|
84
|
-
* deterministic placement (peer ids fold tag + key).
|
|
85
|
-
*/
|
|
86
|
-
tag: string;
|
|
87
|
-
/**
|
|
88
|
-
* Per-task timeout in ms. Default 60_000. Forwarded to the in-DO
|
|
89
|
-
* NimbusLoaderPool's submit calls and to the peer-DO RPC's own
|
|
90
|
-
* NimbusLoaderPool.
|
|
91
|
-
*/
|
|
92
|
-
timeoutMs?: number;
|
|
93
|
-
/**
|
|
94
|
-
* Preamble bundled into every facet (in-DO and inside each peer
|
|
95
|
-
* DO). Same semantics as NimbusLoaderPool's preamble option.
|
|
96
|
-
*/
|
|
97
|
-
preamble?: string;
|
|
98
|
-
/**
|
|
99
|
-
* Wasm modules forwarded to every facet. Same semantics as
|
|
100
|
-
* NimbusLoaderPool's wasmModules option.
|
|
101
|
-
*/
|
|
102
|
-
wasmModules?: Record<string, ArrayBuffer>;
|
|
103
|
-
/**
|
|
104
|
-
* Extra bindings forwarded to every facet. Same semantics as
|
|
105
|
-
* NimbusLoaderPool's extraBindings option.
|
|
106
|
-
*/
|
|
107
|
-
extraBindings?: Record<string, unknown>;
|
|
108
|
-
/**
|
|
109
|
-
* If set, skip the supervisor-RPC binding injection (mirrors
|
|
110
|
-
* NimbusLoaderPool's omitSupervisor flag).
|
|
111
|
-
*/
|
|
112
|
-
omitSupervisor?: boolean;
|
|
113
|
-
/**
|
|
114
|
-
* Invoking process pid, baked into each facet's SUPERVISOR binding so
|
|
115
|
-
* filesystem RPCs (writeBatchStream) are authorized under the caller's
|
|
116
|
-
* credential (mirrors NimbusLoaderPool's supervisorPid). Threaded to both
|
|
117
|
-
* the in-DO loader pool and, via `_rpcFanoutExecute`, the peer-DO pools.
|
|
118
|
-
* npm install passes the shell command's `ctx.pid`; resolve leaves it 0.
|
|
119
|
-
*/
|
|
120
|
-
supervisorPid?: number;
|
|
121
|
-
/**
|
|
122
|
-
* Called once per completed peer-DO dispatch phase with that phase's shard
|
|
123
|
-
* count and elapsed ms. Phases are barriers, so this is what tells a caller
|
|
124
|
-
* whether its fan-out is bounded by shard work or by the number of barriers.
|
|
125
|
-
* Not called on the in-DO path, which has no phases.
|
|
126
|
-
*/
|
|
127
|
-
onDispatchPhase?: (width: number, elapsedMs: number) => void;
|
|
128
|
-
/**
|
|
129
|
-
* Cap on peer DOs this pool will spread one submitMany across. Defaults to
|
|
130
|
-
* MAX_PEER_FANOUT. Tasks beyond the cap bucket into the peers that exist and
|
|
131
|
-
* run through their in-peer pool, so lowering it trades peers for barriers
|
|
132
|
-
* without lowering total concurrency: each peer runs its bucket at
|
|
133
|
-
* concurrency 4, so N peers still resolve 4N tasks at once.
|
|
134
|
-
*
|
|
135
|
-
* A caller sets this when its per-task work is small enough that a peer per
|
|
136
|
-
* task buys nothing but round-trips — one task per peer costs ⌈tasks/
|
|
137
|
-
* FANOUT_PHASE_SIZE⌉ barriers, and each barrier costs a cold sibling start.
|
|
138
|
-
*/
|
|
139
|
-
maxPeers?: number;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Two-tier fan-out pool. Constructed by the supervisor DO; routes
|
|
143
|
-
* each `submitMany` call automatically based on width.
|
|
144
|
-
*
|
|
145
|
-
* Lifetime: cheap to construct (no async init). Multiple submitMany
|
|
146
|
-
* calls share NO state — each is dispatched fresh. The class
|
|
147
|
-
* exists primarily as a clean API surface; per-call dispatch state
|
|
148
|
-
* lives only inside submitMany's promise.
|
|
149
|
-
*/
|
|
150
|
-
export declare class NimbusFanoutPool {
|
|
151
|
-
private readonly env;
|
|
152
|
-
private readonly ctx;
|
|
153
|
-
private readonly opts;
|
|
154
|
-
private readonly coordDoId;
|
|
155
|
-
private readonly coordDoIdShort;
|
|
156
|
-
constructor(env: any, ctx: DurableObjectState, opts: NimbusFanoutPoolOptions);
|
|
157
|
-
/**
|
|
158
|
-
* Dispatch `tasks` across the appropriate topology and return
|
|
159
|
-
* results in input order.
|
|
160
|
-
*
|
|
161
|
-
* Routing:
|
|
162
|
-
* tasks.length < 5 -> coordinator-local NimbusLoaderPool
|
|
163
|
-
* tasks.length >= 5 -> sibling NimbusSession DOs
|
|
164
|
-
*
|
|
165
|
-
* Backpressure: if `tasks.length > MAX_PEER_FANOUT (32)`, tasks
|
|
166
|
-
* are sharded modulo `MAX_PEER_FANOUT` and each shard's bucket
|
|
167
|
-
* runs serially inside its assigned peer DO via the in-peer
|
|
168
|
-
* NimbusLoaderPool's concurrency (capped at 4 there too). A
|
|
169
|
-
* single submitMany call returns when ALL tasks complete (or any
|
|
170
|
-
* throws).
|
|
171
|
-
*
|
|
172
|
-
* `fn` is the user function executed per task. It runs INSIDE a
|
|
173
|
-
* Worker Loader isolate (in the in-DO path) or inside a peer DO's
|
|
174
|
-
* Worker Loader isolate (in the peer-DO path); same trust posture
|
|
175
|
-
* as NimbusLoaderPool.submit. The function is serialized via
|
|
176
|
-
* the vendored serializeFunction (same as NimbusLoaderPool#prepare).
|
|
177
|
-
*/
|
|
178
|
-
submitMany<A, R>(tasks: FanoutTask<A>[], fn: (item: A, env: any) => R | Promise<R>): Promise<R[]>;
|
|
179
|
-
/** Report which topology a task count uses without dispatching. */
|
|
180
|
-
topologyFor(taskCount: number): 'in-do' | 'peer-do' | 'empty';
|
|
181
|
-
/**
|
|
182
|
-
* Compute the deterministic peer-DO id for a task key and peer count.
|
|
183
|
-
*
|
|
184
|
-
* Shape: `nbf:${tag}:${coordDoIdShort}:${shard}` where
|
|
185
|
-
* `shard = hash(key) mod peerCount`. Peer count is
|
|
186
|
-
* `min(tasks.length, MAX_PEER_FANOUT)`.
|
|
187
|
-
*/
|
|
188
|
-
peerSiblingId(key: string, peerCount: number): string;
|
|
189
|
-
private _dispatchInDo;
|
|
190
|
-
private _dispatchPeerDo;
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Stable hash → shard. Uses a fresh djb2 over the key (NOT
|
|
194
|
-
* hashSource) and modulos by peerCount.
|
|
195
|
-
*
|
|
196
|
-
* Why not reuse hashSource: hashSource returns a base-36 string,
|
|
197
|
-
* NOT hex — its alphabet is `[0-9a-z]`. parseInt(str, 16) on a
|
|
198
|
-
* base-36 string aborts at the first non-hex char (any of g-z),
|
|
199
|
-
* which produces extremely poor distribution: keys with the same
|
|
200
|
-
* leading-hex-prefix collide regardless of their suffix. (Seen in
|
|
201
|
-
* the wild: `task-0 .. task-7` all collided onto shard 4.)
|
|
202
|
-
*
|
|
203
|
-
* Deterministic: same key + same peerCount → same shard, every run.
|
|
204
|
-
* Tests use this to predict placement.
|
|
205
|
-
*/
|
|
206
|
-
export declare function hashKeyToShard(key: string, peerCount: number): number;
|
|
207
|
-
//# sourceMappingURL=fanout-pool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fanout-pool.d.ts","sourceRoot":"","sources":["../../src/loaders/fanout-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH;;;;;;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,wDAAwD;AACxD,MAAM,WAAW,uBAAuB;IACtC;;;;;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;AA4BD;;;;;;;;GAQG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,uBAAuB;IAiB5E;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,UAAU,CAAC,CAAC,EAAE,CAAC,EACnB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,EACtB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GACxC,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;CAyJ9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUrE"}
|