@nimbus-sh/worker 0.5.0 → 0.7.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 +2 -2
- package/dist/_shared/preview-host.d.ts +26 -8
- package/dist/_shared/preview-host.d.ts.map +1 -1
- package/dist/_shared/preview-host.js +51 -11
- package/dist/cirrus-npm-cjs.generated.d.ts +1 -1
- package/dist/cirrus-npm-cjs.generated.js +1 -1
- package/dist/facets/cirrus-real.d.ts.map +1 -1
- package/dist/facets/cirrus-real.js +6 -5
- package/dist/facets/compose.d.ts +148 -0
- package/dist/facets/compose.d.ts.map +1 -0
- package/dist/facets/compose.js +146 -0
- package/dist/facets/durable-images.d.ts +18 -5
- package/dist/facets/durable-images.d.ts.map +1 -1
- package/dist/facets/durable-images.js +36 -7
- package/dist/facets/durable-slots.d.ts +1 -1
- package/dist/facets/durable-slots.d.ts.map +1 -1
- package/dist/facets/durable-slots.js +2 -1
- package/dist/facets/esbuild-bundle-pool.d.ts +49 -0
- package/dist/facets/esbuild-bundle-pool.d.ts.map +1 -0
- package/dist/facets/esbuild-bundle-pool.js +122 -0
- package/dist/facets/exec-telemetry.d.ts +8 -0
- package/dist/facets/exec-telemetry.d.ts.map +1 -1
- package/dist/facets/manager.d.ts +337 -123
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +1100 -449
- package/dist/facets/process.d.ts +20 -16
- package/dist/facets/process.d.ts.map +1 -1
- package/dist/facets/process.js +59 -28
- package/dist/facets/real-vite-fs-shim.js +2 -2
- package/dist/facets/resident-identity.d.ts +23 -0
- package/dist/facets/resident-identity.d.ts.map +1 -0
- package/dist/facets/resident-identity.js +31 -0
- package/dist/facets/vite-dev-server.d.ts +25 -47
- package/dist/facets/vite-dev-server.d.ts.map +1 -1
- package/dist/facets/vite-dev-server.js +185 -219
- package/dist/facets/wasm-image-digest.d.ts +25 -0
- package/dist/facets/wasm-image-digest.d.ts.map +1 -0
- package/dist/facets/wasm-image-digest.js +25 -0
- package/dist/facets/wasm-swap-registry.d.ts +51 -92
- package/dist/facets/wasm-swap-registry.d.ts.map +1 -1
- package/dist/facets/wasm-swap-registry.js +68 -227
- package/dist/git/commands.d.ts +0 -1
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +0 -3
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +6 -5
- package/dist/loaders/child-process/spawn-pool.d.ts +3 -2
- package/dist/loaders/child-process/spawn-pool.d.ts.map +1 -1
- package/dist/loaders/child-process/spawn-pool.js +3 -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 -6
- package/dist/loaders/npm-resolve-preamble.d.ts.map +1 -1
- package/dist/loaders/npm-resolve-preamble.js +34 -108
- package/dist/node-shims-artifact.generated.js +3 -3
- package/dist/npm/install-batch-facet.d.ts +3 -2
- package/dist/npm/install-batch-facet.d.ts.map +1 -1
- package/dist/npm/install-batch-facet.js +45 -15
- package/dist/npm/installer.d.ts +22 -17
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +209 -193
- package/dist/npm/pre-bundle-facet.d.ts +1 -1
- package/dist/npm/pre-bundle-facet.d.ts.map +1 -1
- package/dist/npm/pre-bundle-facet.js +1 -1
- package/dist/npm/resolve-facet.d.ts +6 -0
- package/dist/npm/resolve-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.d.ts +21 -20
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +85 -84
- package/dist/npm/semver.d.ts +59 -0
- package/dist/npm/semver.d.ts.map +1 -0
- package/dist/npm/semver.js +226 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +47 -10
- package/dist/router/public-directory.d.ts +5 -1
- package/dist/router/public-directory.d.ts.map +1 -1
- package/dist/router/public-directory.js +9 -2
- package/dist/router/remote-api.d.ts +18 -0
- package/dist/router/remote-api.d.ts.map +1 -1
- package/dist/router/remote-api.js +64 -5
- package/dist/runtime/cpython-resident.d.ts.map +1 -1
- package/dist/runtime/cpython-resident.js +3 -1
- package/dist/runtime/html-entrypoint.d.ts +7 -0
- package/dist/runtime/html-entrypoint.d.ts.map +1 -1
- package/dist/runtime/html-entrypoint.js +18 -2
- package/dist/runtime/node-runner.d.ts +3 -0
- package/dist/runtime/node-runner.d.ts.map +1 -1
- package/dist/runtime/node-runner.js +7 -0
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +305 -29
- package/dist/runtime/opencode-facet-runner.js +2 -2
- package/dist/runtime/package-manager.d.ts +44 -1
- package/dist/runtime/package-manager.d.ts.map +1 -1
- package/dist/runtime/package-manager.js +168 -3
- package/dist/runtime/ruby-resident.d.ts.map +1 -1
- package/dist/runtime/ruby-resident.js +2 -0
- package/dist/session/agent.d.ts.map +1 -1
- package/dist/session/agent.js +28 -1
- package/dist/session/helpers.d.ts +38 -0
- package/dist/session/helpers.d.ts.map +1 -1
- package/dist/session/helpers.js +76 -0
- package/dist/session/init-phases.d.ts +1 -1
- package/dist/session/init-phases.d.ts.map +1 -1
- package/dist/session/init-phases.js +2 -12
- package/dist/session/init.d.ts +15 -1
- package/dist/session/init.d.ts.map +1 -1
- package/dist/session/init.js +91 -603
- package/dist/session/keys.d.ts +4 -0
- package/dist/session/keys.d.ts.map +1 -1
- package/dist/session/keys.js +4 -0
- package/dist/session/nimbus-session.d.ts +90 -23
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +200 -110
- package/dist/session/npm-install-port.d.ts +16 -0
- package/dist/session/npm-install-port.d.ts.map +1 -0
- package/dist/session/npm-install-port.js +37 -0
- package/dist/session/port-capability.d.ts +90 -0
- package/dist/session/port-capability.d.ts.map +1 -1
- package/dist/session/port-capability.js +219 -9
- package/dist/session/programmatic.d.ts +125 -5
- package/dist/session/programmatic.d.ts.map +1 -1
- package/dist/session/programmatic.js +439 -89
- package/dist/session/routes.d.ts +39 -17
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +67 -131
- package/dist/session/rpc.d.ts +39 -16
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +137 -130
- package/dist/session/serving-port.d.ts +27 -0
- package/dist/session/serving-port.d.ts.map +1 -0
- package/dist/session/serving-port.js +27 -0
- package/dist/session/start-real-vite.d.ts +12 -0
- package/dist/session/start-real-vite.d.ts.map +1 -1
- package/dist/session/start-real-vite.js +4 -4
- package/dist/session/supervisor-op.d.ts +41 -4
- package/dist/session/supervisor-op.d.ts.map +1 -1
- package/dist/session/supervisor-op.js +101 -73
- package/dist/session/supervisor-rpc.d.ts +7 -7
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +6 -3
- package/dist/session/vite-command.d.ts +18 -0
- package/dist/session/vite-command.d.ts.map +1 -0
- package/dist/session/vite-command.js +609 -0
- package/dist/session/ws.d.ts +61 -0
- package/dist/session/ws.d.ts.map +1 -1
- package/dist/session/ws.js +122 -12
- package/dist/shell/npm-bin-entrypoints.d.ts +0 -35
- package/dist/shell/npm-bin-entrypoints.d.ts.map +1 -1
- package/dist/shell/npm-bin-entrypoints.js +12 -85
- package/package.json +24 -4
- package/public/_assets/runtime/{node-shims-9e1380d9ee430fcc.js → node-shims-8f8c64edd2a1f0f5.js} +305 -29
- package/public/index.html +1 -1
- package/scripts/bundle-facet-workers.mjs +1 -1
- package/scripts/bundle-npm-cjs.mjs +2 -2
- package/dist/facets/on-demand-bundle-gate.d.ts +0 -65
- package/dist/facets/on-demand-bundle-gate.d.ts.map +0 -1
- package/dist/facets/on-demand-bundle-gate.js +0 -125
- package/dist/npm/install-args.d.ts +0 -21
- package/dist/npm/install-args.d.ts.map +0 -1
- package/dist/npm/install-args.js +0 -70
- package/dist/npm/npm-log.d.ts +0 -31
- package/dist/npm/npm-log.d.ts.map +0 -1
- package/dist/npm/npm-log.js +0 -51
|
@@ -12,16 +12,34 @@
|
|
|
12
12
|
* durable spawn exists to survive. Durable images are kept for the
|
|
13
13
|
* application's life and released only by explicit removal.
|
|
14
14
|
*
|
|
15
|
-
* Two blobs per launch: `runner` is the
|
|
16
|
-
* is a JSON payload of `{ modules, env, vfsWasmModules }
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* them
|
|
15
|
+
* Two blobs per launch: `runner` is the main module's source text,
|
|
16
|
+
* `application` is a JSON payload of `{ modules, env, vfsWasmModules }` plus,
|
|
17
|
+
* when the launch set them, `vfsTextModules`, `mainModule` and `startArgs`.
|
|
18
|
+
* The digests in the journal's `recipe.image` are sha256 hashes of those two
|
|
19
|
+
* payloads, and a self-owned spawn mints them at spawn time; an
|
|
20
|
+
* embedder-owned spawn is given them by its own bookkeeping instead.
|
|
20
21
|
*/
|
|
21
22
|
import { CRED_KERNEL } from '@nimbus-sh/core/runtime/os-contracts.js';
|
|
22
23
|
/** The directory every durable application's image blobs live under. */
|
|
23
24
|
export const DURABLE_IMAGE_DIR = '.nimbus/images';
|
|
24
25
|
const imagePath = (digest) => `${DURABLE_IMAGE_DIR}/${digest}`;
|
|
26
|
+
/** Remove only the owner's blobs that no other retained recipe references. */
|
|
27
|
+
export function purgeDurableWorkerImages(vfs, owned, retained) {
|
|
28
|
+
const keep = new Set([...retained].flatMap((image) => [image.runner, image.application]));
|
|
29
|
+
const candidates = new Set([...owned].flatMap((image) => [image.runner, image.application]));
|
|
30
|
+
const kernel = vfs.as(CRED_KERNEL);
|
|
31
|
+
let removed = 0;
|
|
32
|
+
for (const digest of candidates) {
|
|
33
|
+
if (keep.has(digest) || !/^[a-f0-9]{64}$/.test(digest))
|
|
34
|
+
continue;
|
|
35
|
+
const path = imagePath(digest);
|
|
36
|
+
if (!kernel.exists(path))
|
|
37
|
+
continue;
|
|
38
|
+
kernel.unlink(path);
|
|
39
|
+
removed += 1;
|
|
40
|
+
}
|
|
41
|
+
return removed;
|
|
42
|
+
}
|
|
25
43
|
async function sha256Hex(text) {
|
|
26
44
|
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(text));
|
|
27
45
|
return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');
|
|
@@ -37,10 +55,15 @@ export async function persistDurableWorkerImage(vfs, workerCode, payload) {
|
|
|
37
55
|
kernel.mkdir(DURABLE_IMAGE_DIR, { recursive: true });
|
|
38
56
|
const runner = await sha256Hex(workerCode);
|
|
39
57
|
kernel.writeFile(imagePath(runner), workerCode);
|
|
58
|
+
// Optional members are omitted rather than written null so an unchanged
|
|
59
|
+
// launch keeps the digest it had before the member existed.
|
|
40
60
|
const applicationPayload = JSON.stringify({
|
|
41
61
|
modules: payload.modules,
|
|
42
62
|
env: payload.env ?? null,
|
|
43
63
|
vfsWasmModules: payload.vfsWasmModules ?? null,
|
|
64
|
+
...(payload.vfsTextModules !== undefined ? { vfsTextModules: payload.vfsTextModules } : {}),
|
|
65
|
+
...(payload.mainModule !== undefined ? { mainModule: payload.mainModule } : {}),
|
|
66
|
+
...(payload.startArgs !== undefined ? { startArgs: payload.startArgs } : {}),
|
|
44
67
|
});
|
|
45
68
|
const application = await sha256Hex(applicationPayload);
|
|
46
69
|
kernel.writeFile(imagePath(application), applicationPayload);
|
|
@@ -65,11 +88,17 @@ export async function resolveDurableWorkerImage(vfs, recipe) {
|
|
|
65
88
|
return null;
|
|
66
89
|
}
|
|
67
90
|
const runner = new TextDecoder().decode(runnerBytes);
|
|
68
|
-
const { modules = {}, env = null, vfsWasmModules = undefined } = JSON.parse(new TextDecoder().decode(applicationBytes));
|
|
91
|
+
const { modules = {}, env = null, vfsWasmModules = undefined, vfsTextModules, mainModule, startArgs, } = JSON.parse(new TextDecoder().decode(applicationBytes));
|
|
92
|
+
// The recipe's own record of the main module wins when the blob predates
|
|
93
|
+
// the member; both say the same thing for any launch written since.
|
|
94
|
+
const main = mainModule ?? recipe.mainModule ?? 'worker.js';
|
|
69
95
|
return {
|
|
70
96
|
env: env ?? null,
|
|
71
97
|
globalOutbound: undefined,
|
|
72
|
-
modules: {
|
|
98
|
+
modules: { ...modules, [main]: runner },
|
|
99
|
+
mainModule: main,
|
|
100
|
+
...(startArgs !== undefined ? { startArgs } : {}),
|
|
73
101
|
...(vfsWasmModules !== null ? { vfsWasmModules } : {}),
|
|
102
|
+
...(vfsTextModules !== undefined ? { vfsTextModules } : {}),
|
|
74
103
|
};
|
|
75
104
|
}
|
|
@@ -41,5 +41,5 @@ export declare function acquireDurableFacetSlot(ctx: DurableObjectState, owner:
|
|
|
41
41
|
* step of explicit removal, after the facet's SQLite is already gone. Answers
|
|
42
42
|
* the freed name, or null when the owner held nothing.
|
|
43
43
|
*/
|
|
44
|
-
export declare function freeDurableFacetSlot(ctx: DurableObjectState, owner: string): Promise<string | null>;
|
|
44
|
+
export declare function freeDurableFacetSlot(ctx: DurableObjectState, owner: string, beforeFree?: (name: string) => void): Promise<string | null>;
|
|
45
45
|
//# sourceMappingURL=durable-slots.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-slots.d.ts","sourceRoot":"","sources":["../../src/facets/durable-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAUH,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"durable-slots.d.ts","sourceRoot":"","sources":["../../src/facets/durable-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAUH,kDAAkD;AAClD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAClC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAaxB"}
|
|
@@ -78,11 +78,12 @@ export async function acquireDurableFacetSlot(ctx, owner) {
|
|
|
78
78
|
* step of explicit removal, after the facet's SQLite is already gone. Answers
|
|
79
79
|
* the freed name, or null when the owner held nothing.
|
|
80
80
|
*/
|
|
81
|
-
export async function freeDurableFacetSlot(ctx, owner) {
|
|
81
|
+
export async function freeDurableFacetSlot(ctx, owner, beforeFree) {
|
|
82
82
|
return ctx.storage.transaction(async (txn) => {
|
|
83
83
|
const held = await txn.get(ownerKey(owner));
|
|
84
84
|
if (typeof held !== 'number')
|
|
85
85
|
return null;
|
|
86
|
+
beforeFree?.(durableFacetName(held));
|
|
86
87
|
await txn.delete(ownerKey(owner));
|
|
87
88
|
const free = await txn.get(FREE_KEY);
|
|
88
89
|
const freeList = Array.isArray(free) ? free.filter((n) => typeof n === 'number') : [];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EsbuildBundlePool — the session's single esbuild facet pool.
|
|
3
|
+
*
|
|
4
|
+
* Install-time pre-bundling and on-demand /@modules/ bundling dispatch the
|
|
5
|
+
* same worker (PRE_BUNDLE_PREAMBLE + esbuild.wasm, one slot). When each
|
|
6
|
+
* pipeline built its own IsolatePool the supervisor retained two copies of
|
|
7
|
+
* the ~12 MiB wasm bytes and warmed two loader slots per session, and the
|
|
8
|
+
* two pools never queued behind each other. One pool, owned by the session,
|
|
9
|
+
* holds one wasm copy — leased once from the shared supervisor allocation
|
|
10
|
+
* budget, the way the pre-bundler already accounted for its own — for as
|
|
11
|
+
* long as the installer and dev server live, and is disposed with them.
|
|
12
|
+
*
|
|
13
|
+
* Construction is lazy and everything heavy is imported on first use so
|
|
14
|
+
* the fabric/preamble/wasm subgraph stays out of the cold script-eval
|
|
15
|
+
* graph of sessions that never bundle.
|
|
16
|
+
*/
|
|
17
|
+
import type { IsolatePool } from '@nimbus-sh/fabric/isolate-pool.js';
|
|
18
|
+
/** The pool surface both bundling pipelines dispatch through. */
|
|
19
|
+
export type BundlePool = Pick<IsolatePool, 'submit'>;
|
|
20
|
+
/** What a bundling pipeline receives from its host. */
|
|
21
|
+
export interface BundlePoolProvider {
|
|
22
|
+
/** The session's pool, constructed on first call. */
|
|
23
|
+
acquire(): Promise<BundlePool>;
|
|
24
|
+
}
|
|
25
|
+
export declare class EsbuildBundlePool implements BundlePoolProvider {
|
|
26
|
+
private readonly env;
|
|
27
|
+
private readonly ctx;
|
|
28
|
+
private pool;
|
|
29
|
+
private pending;
|
|
30
|
+
/** Releases the wasm bytes' supervisor credit; held until dispose(). */
|
|
31
|
+
private releaseWasmCredit;
|
|
32
|
+
/** Bumped by dispose() so a construction it interrupted tears itself down. */
|
|
33
|
+
private generation;
|
|
34
|
+
constructor(env: unknown, ctx: DurableObjectState);
|
|
35
|
+
/**
|
|
36
|
+
* Callers MUST acquire the pool before taking any slice lease: the
|
|
37
|
+
* first construction reserves the full supervisor budget while the wasm
|
|
38
|
+
* bytes are fetched, so a caller already holding slice credit would
|
|
39
|
+
* wait on itself.
|
|
40
|
+
*/
|
|
41
|
+
acquire(): Promise<IsolatePool>;
|
|
42
|
+
private construct;
|
|
43
|
+
/**
|
|
44
|
+
* Tear the pool down with its host. A later acquire() constructs a fresh
|
|
45
|
+
* pool, so a session that installs again after a teardown still bundles.
|
|
46
|
+
*/
|
|
47
|
+
dispose(): void;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=esbuild-bundle-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esbuild-bundle-pool.d.ts","sourceRoot":"","sources":["../../src/facets/esbuild-bundle-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AASrE,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAErD,uDAAuD;AACvD,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;CAChC;AAQD,qBAAa,iBAAkB,YAAW,kBAAkB;IASxD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IATtB,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,OAAO,CAAqC;IACpD,wEAAwE;IACxE,OAAO,CAAC,iBAAiB,CAA6B;IACtD,8EAA8E;IAC9E,OAAO,CAAC,UAAU,CAAK;gBAGJ,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,kBAAkB;IAG1C;;;;;OAKG;IACH,OAAO,IAAI,OAAO,CAAC,WAAW,CAAC;YAqBjB,SAAS;IAmDvB;;;OAGG;IACH,OAAO,IAAI,IAAI;CAYhB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { acquireResidentSupervisorAllocation } from '@nimbus-sh/platform/heavy-alloc-coord.js';
|
|
2
|
+
import { PRE_BUNDLE_CONCURRENCY, PRE_BUNDLE_SLICE_CAP_BYTES, SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES, } from '@nimbus-sh/platform/limits.js';
|
|
3
|
+
function hasAssetsFetcher(env) {
|
|
4
|
+
if (typeof env !== 'object' || env === null)
|
|
5
|
+
return false;
|
|
6
|
+
const assets = Reflect.get(env, 'ASSETS');
|
|
7
|
+
return typeof assets === 'object' && assets !== null && typeof Reflect.get(assets, 'fetch') === 'function';
|
|
8
|
+
}
|
|
9
|
+
export class EsbuildBundlePool {
|
|
10
|
+
env;
|
|
11
|
+
ctx;
|
|
12
|
+
pool = null;
|
|
13
|
+
pending = null;
|
|
14
|
+
/** Releases the wasm bytes' supervisor credit; held until dispose(). */
|
|
15
|
+
releaseWasmCredit = null;
|
|
16
|
+
/** Bumped by dispose() so a construction it interrupted tears itself down. */
|
|
17
|
+
generation = 0;
|
|
18
|
+
constructor(env, ctx) {
|
|
19
|
+
this.env = env;
|
|
20
|
+
this.ctx = ctx;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Callers MUST acquire the pool before taking any slice lease: the
|
|
24
|
+
* first construction reserves the full supervisor budget while the wasm
|
|
25
|
+
* bytes are fetched, so a caller already holding slice credit would
|
|
26
|
+
* wait on itself.
|
|
27
|
+
*/
|
|
28
|
+
acquire() {
|
|
29
|
+
if (this.pool)
|
|
30
|
+
return Promise.resolve(this.pool);
|
|
31
|
+
if (this.pending)
|
|
32
|
+
return this.pending;
|
|
33
|
+
const generation = this.generation;
|
|
34
|
+
const pending = this.construct().then(({ pool, releaseWasmCredit }) => {
|
|
35
|
+
if (this.generation !== generation) {
|
|
36
|
+
// dispose() ran while the wasm bytes were in flight.
|
|
37
|
+
try {
|
|
38
|
+
pool.dispose();
|
|
39
|
+
}
|
|
40
|
+
catch { /* best-effort */ }
|
|
41
|
+
releaseWasmCredit();
|
|
42
|
+
throw new Error('EsbuildBundlePool: disposed during construction');
|
|
43
|
+
}
|
|
44
|
+
this.pool = pool;
|
|
45
|
+
this.releaseWasmCredit = releaseWasmCredit;
|
|
46
|
+
return pool;
|
|
47
|
+
}).finally(() => {
|
|
48
|
+
if (this.pending === pending)
|
|
49
|
+
this.pending = null;
|
|
50
|
+
});
|
|
51
|
+
this.pending = pending;
|
|
52
|
+
return pending;
|
|
53
|
+
}
|
|
54
|
+
async construct() {
|
|
55
|
+
if (!hasAssetsFetcher(this.env)) {
|
|
56
|
+
throw new Error('EsbuildBundlePool: env.ASSETS binding missing — the esbuild wasm asset cannot be fetched');
|
|
57
|
+
}
|
|
58
|
+
const env = this.env;
|
|
59
|
+
const [{ IsolatePool }, { PRE_BUNDLE_PREAMBLE }, { fetchEsbuildWasmBytes }] = await Promise.all([
|
|
60
|
+
import('@nimbus-sh/fabric/isolate-pool.js'),
|
|
61
|
+
import('../loaders/pre-bundle-preamble.js'),
|
|
62
|
+
import('../runtime/esbuild-wasm-bytes.js'),
|
|
63
|
+
]);
|
|
64
|
+
// Resident, and sized to what the pool will KEEP — not the whole budget.
|
|
65
|
+
//
|
|
66
|
+
// The full-budget claim this used to make is grantable exactly once: the
|
|
67
|
+
// lease it shrinks to becomes a permanent floor, so a second pool
|
|
68
|
+
// construction asked for 40 MiB against 28.1 MiB that could ever be free
|
|
69
|
+
// and parked in the FIFO with no error and no CPU. Measured on a
|
|
70
|
+
// deployed worker: capacity 41,943,040, resident 11,907,565, queued 1 for
|
|
71
|
+
// 222 s with the isolate healthy the whole time — and because the queue
|
|
72
|
+
// refuses everyone behind a waiter, the whole session stopped making
|
|
73
|
+
// progress. The bound below is the same one the payload is checked
|
|
74
|
+
// against, so the slice cap stays free for the work the pool exists for.
|
|
75
|
+
const maxRetainedWasmBytes = SUPERVISOR_IN_FLIGHT_ALLOCATION_BUDGET_BYTES - PRE_BUNDLE_SLICE_CAP_BYTES;
|
|
76
|
+
const setupAllocation = await acquireResidentSupervisorAllocation(maxRetainedWasmBytes);
|
|
77
|
+
let retained = false;
|
|
78
|
+
try {
|
|
79
|
+
const wasmBytes = await fetchEsbuildWasmBytes(env);
|
|
80
|
+
if (wasmBytes.byteLength > maxRetainedWasmBytes) {
|
|
81
|
+
throw new RangeError(`esbuild wasm payload ${wasmBytes.byteLength} exceeds the ${maxRetainedWasmBytes}-byte retained budget`);
|
|
82
|
+
}
|
|
83
|
+
// IsolatePool keeps the constructor-time module bytes until dispose(),
|
|
84
|
+
// so retain their exact credit rather than treating construction as a
|
|
85
|
+
// handoff that immediately frees the ArrayBuffer.
|
|
86
|
+
setupAllocation.shrinkTo(wasmBytes.byteLength);
|
|
87
|
+
const pool = new IsolatePool(env, this.ctx, {
|
|
88
|
+
concurrency: PRE_BUNDLE_CONCURRENCY,
|
|
89
|
+
timeoutMs: 60_000,
|
|
90
|
+
retries: 0,
|
|
91
|
+
tag: 'esbuild-bundle',
|
|
92
|
+
preamble: PRE_BUNDLE_PREAMBLE,
|
|
93
|
+
wasmModules: { 'esbuild.wasm': wasmBytes },
|
|
94
|
+
});
|
|
95
|
+
retained = true;
|
|
96
|
+
return { pool, releaseWasmCredit: setupAllocation.release };
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
if (!retained)
|
|
100
|
+
setupAllocation.release();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Tear the pool down with its host. A later acquire() constructs a fresh
|
|
105
|
+
* pool, so a session that installs again after a teardown still bundles.
|
|
106
|
+
*/
|
|
107
|
+
dispose() {
|
|
108
|
+
this.generation++;
|
|
109
|
+
const pool = this.pool;
|
|
110
|
+
this.pool = null;
|
|
111
|
+
this.pending = null;
|
|
112
|
+
if (pool) {
|
|
113
|
+
try {
|
|
114
|
+
pool.dispose();
|
|
115
|
+
}
|
|
116
|
+
catch { /* best-effort */ }
|
|
117
|
+
}
|
|
118
|
+
const release = this.releaseWasmCredit;
|
|
119
|
+
this.releaseWasmCredit = null;
|
|
120
|
+
release?.();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -57,6 +57,14 @@ export interface ExecTelemetryRecord {
|
|
|
57
57
|
fsRpcReads: number;
|
|
58
58
|
/** Whether the prefetch bundle was served from cache (no VFS walk). */
|
|
59
59
|
cacheHit: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Durable Object turns the bundle build was paged across — the alarm
|
|
62
|
+
* round trips `TurnBudget` took before the process could start. 0 when the
|
|
63
|
+
* whole build fit in the turn that asked for it, which is every cache hit
|
|
64
|
+
* and every small tree; the count is what says a large tree cost turns
|
|
65
|
+
* rather than a held thread.
|
|
66
|
+
*/
|
|
67
|
+
turns: number;
|
|
60
68
|
/** Exit code, for cross-referencing telemetry against failures. */
|
|
61
69
|
exitCode: number;
|
|
62
70
|
/** Wall-clock at record time (supervisor side). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec-telemetry.d.ts","sourceRoot":"","sources":["../../src/facets/exec-telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd;0EACsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB;;gEAE4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,mBAAmB,EACnB,QAAQ,GAAG,OAAO,GAAG,gBAAgB,GAAG,aAAa,GAAG,eAAe,GAAG,eAAe,CAC1F,CAAC;AAKF;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAIlE;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,IAAI,mBAAmB,EAAE,CAEzD;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
1
|
+
{"version":3,"file":"exec-telemetry.d.ts","sourceRoot":"","sources":["../../src/facets/exec-telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd;0EACsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;;;OASG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,SAAS,EAAE,MAAM,CAAC;IAClB;;gEAE4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,mBAAmB,EACnB,QAAQ,GAAG,OAAO,GAAG,gBAAgB,GAAG,aAAa,GAAG,eAAe,GAAG,eAAe,CAC1F,CAAC;AAKF;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB,GAAG,IAAI,CAIlE;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,IAAI,mBAAmB,EAAE,CAEzD;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|