@nimbus-sh/fabric 0.8.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 +98 -11
- 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 +102 -29
- package/dist/budgets.d.ts.map +1 -1
- package/dist/budgets.js +266 -44
- package/dist/do-calls.d.ts +20 -0
- package/dist/do-calls.d.ts.map +1 -1
- package/dist/do-calls.js +24 -11
- package/dist/fanout.d.ts +40 -32
- package/dist/fanout.d.ts.map +1 -1
- package/dist/fanout.js +48 -51
- package/dist/fenced-work.d.ts +3 -3
- package/dist/fenced-work.js +3 -3
- package/dist/host-wasm.d.ts +29 -0
- package/dist/host-wasm.d.ts.map +1 -0
- package/dist/host-wasm.js +31 -0
- package/dist/image-store.d.ts +1 -1
- package/dist/image-store.d.ts.map +1 -1
- package/dist/image-store.js +33 -1
- 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 +40 -23
- package/dist/isolate-pool.d.ts.map +1 -1
- package/dist/isolate-pool.js +105 -55
- package/dist/process-fabric.d.ts +26 -11
- package/dist/process-fabric.d.ts.map +1 -1
- package/dist/process-fabric.js +44 -0
- package/dist/timers.d.ts +12 -0
- package/dist/timers.d.ts.map +1 -1
- package/dist/timers.js +44 -9
- package/dist/vendor/types.d.ts +11 -5
- package/dist/vendor/types.d.ts.map +1 -1
- package/dist/workerd-facet-host.d.ts.map +1 -1
- package/dist/workerd-facet-host.js +35 -30
- package/package.json +4 -4
- package/src/bindings.ts +121 -98
- package/src/budgets.ts +311 -53
- package/src/do-calls.ts +45 -11
- package/src/fanout.ts +62 -53
- package/src/fenced-work.ts +3 -3
- package/src/host-wasm.ts +41 -0
- package/src/image-store.ts +29 -2
- package/src/inner-do-env.ts +213 -0
- package/src/isolate-pool.ts +145 -75
- package/src/process-fabric.ts +55 -13
- package/src/timers.ts +45 -9
- package/src/vendor/types.ts +11 -5
- package/src/workerd-facet-host.ts +36 -31
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inner-do-env.ts — a classic Durable Object binding inside an inner Worker.
|
|
3
|
+
*
|
|
4
|
+
* `nimbus wrangler dev` loads the user's Worker as a dynamic worker, and its
|
|
5
|
+
* Durable Object bindings run as facets of the session Durable Object. The
|
|
6
|
+
* binding the loader passes (`NimbusDurableObjectNamespace`, an entrypoint of
|
|
7
|
+
* the session's isolate) answers RPC, so it cannot be the inner Worker's
|
|
8
|
+
* namespace: a DurableObjectNamespace's API is synchronous (`env.P.get(
|
|
9
|
+
* env.P.idFromName('x'))` takes no await), and an RpcPromise cannot travel as
|
|
10
|
+
* an argument ("Could not serialize object of type RpcPromise").
|
|
11
|
+
*
|
|
12
|
+
* So a module the inner Worker runs before any of its own code (its main
|
|
13
|
+
* module's first import, `innerWorkerModules`) replaces each such binding in
|
|
14
|
+
* the isolate's env, which every handler, entrypoint and Durable Object of the
|
|
15
|
+
* isolate sees, with a local namespace. Ids are made locally, and `get`
|
|
16
|
+
* answers at once an RPC stub (`new RpcStub(target)`) of a local target that
|
|
17
|
+
* relays each member the stub's caller reaches (a call, a read, or a path
|
|
18
|
+
* through members, fetch included) to the binding's `callOn` or `getOn`,
|
|
19
|
+
* which the session runs on the object's facet. An RPC stub is what a
|
|
20
|
+
* Durable Object stub is to the runtime: callable by any method name, read by
|
|
21
|
+
* any property name, pipelined, bound to its request, and transferable, as an
|
|
22
|
+
* argument or an answer, where an entrypoint of a dynamically-loaded Worker
|
|
23
|
+
* is not. Arguments and answers cross natively, stubs, functions and streams
|
|
24
|
+
* included.
|
|
25
|
+
*
|
|
26
|
+
* Its prototype is not RpcStub's but one shaped as a Durable Object stub's:
|
|
27
|
+
* its constructor is a class `DurableObject` that cannot be constructed, its
|
|
28
|
+
* tag is 'DurableObject', and it has no `dup` or Symbol.dispose of its own,
|
|
29
|
+
* so `dup` is a member, which the runtime refuses as on Cloudflare. It
|
|
30
|
+
* differs from a Durable Object stub in two ways the runtime fixes. `typeof`
|
|
31
|
+
* is 'function'. And it is not persistent, so a Worker Loader env cannot carry
|
|
32
|
+
* it ("RpcStub cannot be serialized in this context because it is not a
|
|
33
|
+
* persistent stub"): the loader shim (NimbusLoaderRPC) keeps a child's code
|
|
34
|
+
* and loads it again in each later request, so the child's env can carry
|
|
35
|
+
* nothing made in one request, the session's own stubs included.
|
|
36
|
+
*/
|
|
37
|
+
import type { RpcStub, WorkerEntrypoint } from 'cloudflare:workers';
|
|
38
|
+
/**
|
|
39
|
+
* The id string a name gives: deterministic (FNV-style, 64-bit hex), with the
|
|
40
|
+
* prefix `name:` so it never collides with a `uniq:` id. Self-contained: its
|
|
41
|
+
* source also runs in the inner isolate (innerDoAdapter).
|
|
42
|
+
*/
|
|
43
|
+
export declare function innerDoIdFromName(name: string): string;
|
|
44
|
+
/** What the binding the loader passes answers: one access to one object. */
|
|
45
|
+
export interface InnerDoRemote {
|
|
46
|
+
/** The member of object `id` at `path` (names from the object down), called with `args`. */
|
|
47
|
+
callOn(id: string, path: string[], args: unknown[]): Promise<unknown>;
|
|
48
|
+
/** The member of object `id` at `path`, read. */
|
|
49
|
+
getOn(id: string, path: string[]): Promise<unknown>;
|
|
50
|
+
}
|
|
51
|
+
/** What the adapter runs over: the inner isolate's `cloudflare:workers`. */
|
|
52
|
+
export interface InnerDoRuntime {
|
|
53
|
+
env: object;
|
|
54
|
+
WorkerEntrypoint: typeof WorkerEntrypoint;
|
|
55
|
+
RpcStub: typeof RpcStub;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The adapter, as it runs in the inner isolate: it replaces each of `names`
|
|
59
|
+
* in `runtime.env` that holds the binding with a local DurableObjectNamespace,
|
|
60
|
+
* and answers the class check the main module exports. `main` is the main
|
|
61
|
+
* module's namespace. Self-contained (serialized with toString): it reaches
|
|
62
|
+
* nothing outside itself but its arguments.
|
|
63
|
+
*/
|
|
64
|
+
export declare function innerDoAdapter(idFromName: (name: string) => string, names: readonly string[], main: object, runtime: InnerDoRuntime): {
|
|
65
|
+
NimbusDurableObjectClasses: unknown;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* The modules an inner Worker runs with Durable Object bindings `names`: its
|
|
69
|
+
* bundle as the main module, whose first import is the adapter (so the
|
|
70
|
+
* adapter has run before any of the Worker's code) and which exports the
|
|
71
|
+
* class check as `classesEntrypoint`, and the adapter. The import shares the
|
|
72
|
+
* bundle's first line, so line numbers stay the bundle's. A Worker with no
|
|
73
|
+
* such binding runs its bundle as it is, and has no class check (null).
|
|
74
|
+
*
|
|
75
|
+
* `classesEntrypoint` is a name the bundle never spells, so it exports no
|
|
76
|
+
* such name itself (a bundler prints an ASCII name as it is).
|
|
77
|
+
*/
|
|
78
|
+
export declare function innerWorkerModules(bundle: string, names: readonly string[]): {
|
|
79
|
+
mainModule: string;
|
|
80
|
+
modules: Record<string, string>;
|
|
81
|
+
classesEntrypoint: string | null;
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=inner-do-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inner-do-env.d.ts","sourceRoot":"","sources":["../src/inner-do-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGpE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWtD;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,4FAA4F;IAC5F,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,iDAAiD;IACjD,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD;AAED,4EAA4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,OAAO,EAAE,OAAO,OAAO,CAAC;CACzB;AAID;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,EACpC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,GACtB;IAAE,0BAA0B,EAAE,OAAO,CAAA;CAAE,CAuFzC;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAiBA"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inner-do-env.ts — a classic Durable Object binding inside an inner Worker.
|
|
3
|
+
*
|
|
4
|
+
* `nimbus wrangler dev` loads the user's Worker as a dynamic worker, and its
|
|
5
|
+
* Durable Object bindings run as facets of the session Durable Object. The
|
|
6
|
+
* binding the loader passes (`NimbusDurableObjectNamespace`, an entrypoint of
|
|
7
|
+
* the session's isolate) answers RPC, so it cannot be the inner Worker's
|
|
8
|
+
* namespace: a DurableObjectNamespace's API is synchronous (`env.P.get(
|
|
9
|
+
* env.P.idFromName('x'))` takes no await), and an RpcPromise cannot travel as
|
|
10
|
+
* an argument ("Could not serialize object of type RpcPromise").
|
|
11
|
+
*
|
|
12
|
+
* So a module the inner Worker runs before any of its own code (its main
|
|
13
|
+
* module's first import, `innerWorkerModules`) replaces each such binding in
|
|
14
|
+
* the isolate's env, which every handler, entrypoint and Durable Object of the
|
|
15
|
+
* isolate sees, with a local namespace. Ids are made locally, and `get`
|
|
16
|
+
* answers at once an RPC stub (`new RpcStub(target)`) of a local target that
|
|
17
|
+
* relays each member the stub's caller reaches (a call, a read, or a path
|
|
18
|
+
* through members, fetch included) to the binding's `callOn` or `getOn`,
|
|
19
|
+
* which the session runs on the object's facet. An RPC stub is what a
|
|
20
|
+
* Durable Object stub is to the runtime: callable by any method name, read by
|
|
21
|
+
* any property name, pipelined, bound to its request, and transferable, as an
|
|
22
|
+
* argument or an answer, where an entrypoint of a dynamically-loaded Worker
|
|
23
|
+
* is not. Arguments and answers cross natively, stubs, functions and streams
|
|
24
|
+
* included.
|
|
25
|
+
*
|
|
26
|
+
* Its prototype is not RpcStub's but one shaped as a Durable Object stub's:
|
|
27
|
+
* its constructor is a class `DurableObject` that cannot be constructed, its
|
|
28
|
+
* tag is 'DurableObject', and it has no `dup` or Symbol.dispose of its own,
|
|
29
|
+
* so `dup` is a member, which the runtime refuses as on Cloudflare. It
|
|
30
|
+
* differs from a Durable Object stub in two ways the runtime fixes. `typeof`
|
|
31
|
+
* is 'function'. And it is not persistent, so a Worker Loader env cannot carry
|
|
32
|
+
* it ("RpcStub cannot be serialized in this context because it is not a
|
|
33
|
+
* persistent stub"): the loader shim (NimbusLoaderRPC) keeps a child's code
|
|
34
|
+
* and loads it again in each later request, so the child's env can carry
|
|
35
|
+
* nothing made in one request, the session's own stubs included.
|
|
36
|
+
*/
|
|
37
|
+
import { ESBUILD_NAME_MODULE_SHIM } from '@nimbus-sh/core/_shared/esbuild-facet-shim.js';
|
|
38
|
+
/**
|
|
39
|
+
* The id string a name gives: deterministic (FNV-style, 64-bit hex), with the
|
|
40
|
+
* prefix `name:` so it never collides with a `uniq:` id. Self-contained: its
|
|
41
|
+
* source also runs in the inner isolate (innerDoAdapter).
|
|
42
|
+
*/
|
|
43
|
+
export function innerDoIdFromName(name) {
|
|
44
|
+
let h1 = 0xdeadbeef ^ name.length;
|
|
45
|
+
let h2 = 0x41c6ce57 ^ name.length;
|
|
46
|
+
for (let i = 0; i < name.length; i++) {
|
|
47
|
+
const ch = name.charCodeAt(i);
|
|
48
|
+
h1 = Math.imul(h1 ^ ch, 2654435761);
|
|
49
|
+
h2 = Math.imul(h2 ^ ch, 1597334677);
|
|
50
|
+
}
|
|
51
|
+
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
|
52
|
+
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
|
|
53
|
+
return 'name:' + (h1 >>> 0).toString(16).padStart(8, '0') + (h2 >>> 0).toString(16).padStart(8, '0');
|
|
54
|
+
}
|
|
55
|
+
/** The entrypoint a build asks which Durable Object classes are missing, unless the bundle spells it. */
|
|
56
|
+
const CLASSES_ENTRYPOINT = 'NimbusDurableObjectClasses';
|
|
57
|
+
/**
|
|
58
|
+
* The adapter, as it runs in the inner isolate: it replaces each of `names`
|
|
59
|
+
* in `runtime.env` that holds the binding with a local DurableObjectNamespace,
|
|
60
|
+
* and answers the class check the main module exports. `main` is the main
|
|
61
|
+
* module's namespace. Self-contained (serialized with toString): it reaches
|
|
62
|
+
* nothing outside itself but its arguments.
|
|
63
|
+
*/
|
|
64
|
+
export function innerDoAdapter(idFromName, names, main, runtime) {
|
|
65
|
+
/** A Durable Object id: its string, and the name it was made from. */
|
|
66
|
+
class DurableObjectId {
|
|
67
|
+
name;
|
|
68
|
+
#id;
|
|
69
|
+
constructor(id, name) {
|
|
70
|
+
this.#id = id;
|
|
71
|
+
if (name !== undefined)
|
|
72
|
+
this.name = name;
|
|
73
|
+
}
|
|
74
|
+
toString() { return this.#id; }
|
|
75
|
+
equals(other) { return other instanceof DurableObjectId && String(other) === this.#id; }
|
|
76
|
+
}
|
|
77
|
+
/** Whether `value` is the binding the loader passes (an RPC stub's methods are its properties). */
|
|
78
|
+
function isRemote(value) {
|
|
79
|
+
return value !== null && (typeof value === 'object' || typeof value === 'function')
|
|
80
|
+
&& typeof Reflect.get(value, 'callOn') === 'function' && typeof Reflect.get(value, 'getOn') === 'function';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The member of object `id` at `path`, as the runtime reaches it in an RPC
|
|
84
|
+
* to the stub: called, read (it is thenable, and the runtime awaits what a
|
|
85
|
+
* read answers), or walked through to one of its own members (the runtime
|
|
86
|
+
* walks a path through own properties only, so every name is reported as
|
|
87
|
+
* one). At the empty path it is the stub's target.
|
|
88
|
+
*/
|
|
89
|
+
function member(remote, id, path) {
|
|
90
|
+
const next = (name) => member(remote, id, [...path, name]);
|
|
91
|
+
return new Proxy((..._args) => undefined, {
|
|
92
|
+
apply: (_target, _self, args) => remote.callOn(id, [...path], args),
|
|
93
|
+
get: (target, name) => {
|
|
94
|
+
if (name === 'then') {
|
|
95
|
+
return (resolve, reject) => remote.getOn(id, [...path]).then(resolve, reject);
|
|
96
|
+
}
|
|
97
|
+
return typeof name === 'string' ? next(name) : Reflect.get(target, name);
|
|
98
|
+
},
|
|
99
|
+
getOwnPropertyDescriptor: (target, name) => (typeof name === 'string' && name !== 'then'
|
|
100
|
+
? { value: next(name), writable: true, enumerable: true, configurable: true }
|
|
101
|
+
: Reflect.getOwnPropertyDescriptor(target, name)),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* A stub's prototype, as a Durable Object stub's shows: its constructor
|
|
106
|
+
* cannot be called or constructed, and it is tagged 'DurableObject'.
|
|
107
|
+
*/
|
|
108
|
+
const stubPrototype = Object.create(Object.prototype, {
|
|
109
|
+
constructor: {
|
|
110
|
+
value: function DurableObject() { throw new TypeError('Illegal constructor'); },
|
|
111
|
+
writable: true,
|
|
112
|
+
configurable: true,
|
|
113
|
+
},
|
|
114
|
+
[Symbol.toStringTag]: { value: 'DurableObject', configurable: true },
|
|
115
|
+
});
|
|
116
|
+
/** Asked once by a build: which classes the main module does not export. */
|
|
117
|
+
class NimbusDurableObjectClasses extends runtime.WorkerEntrypoint {
|
|
118
|
+
missing(classNames) {
|
|
119
|
+
return classNames.filter((name) => typeof Reflect.get(main, name) !== 'function');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** env.MY_DO: the namespace, made locally; its stubs relay to `remote`. */
|
|
123
|
+
class DurableObjectNamespace {
|
|
124
|
+
#remote;
|
|
125
|
+
constructor(remote) { this.#remote = remote; }
|
|
126
|
+
idFromName(name) { return new DurableObjectId(idFromName(String(name)), String(name)); }
|
|
127
|
+
newUniqueId() { return new DurableObjectId('uniq:' + crypto.randomUUID().replaceAll('-', '')); }
|
|
128
|
+
idFromString(id) { return new DurableObjectId(String(id)); }
|
|
129
|
+
get(id) {
|
|
130
|
+
const at = id instanceof DurableObjectId ? id : new DurableObjectId(String(id));
|
|
131
|
+
const stub = Object.setPrototypeOf(new runtime.RpcStub(member(this.#remote, String(at), [])), stubPrototype);
|
|
132
|
+
// As a Durable Object stub has them: its own, enumerable, in this order.
|
|
133
|
+
return Object.defineProperties(stub, {
|
|
134
|
+
name: { value: at.name, enumerable: true },
|
|
135
|
+
id: { value: at, enumerable: true },
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
getByName(name) { return this.get(this.idFromName(name)); }
|
|
139
|
+
jurisdiction() { return this; }
|
|
140
|
+
}
|
|
141
|
+
for (const name of names) {
|
|
142
|
+
const remote = Reflect.get(runtime.env, name);
|
|
143
|
+
if (isRemote(remote))
|
|
144
|
+
Reflect.set(runtime.env, name, new DurableObjectNamespace(remote));
|
|
145
|
+
}
|
|
146
|
+
return { NimbusDurableObjectClasses };
|
|
147
|
+
}
|
|
148
|
+
/** The inner Worker's own module, as bundled, and the adapter's. */
|
|
149
|
+
const MAIN_MODULE = 'worker.js';
|
|
150
|
+
const ADAPTER_MODULE = 'nimbus-do-env.js';
|
|
151
|
+
/**
|
|
152
|
+
* The modules an inner Worker runs with Durable Object bindings `names`: its
|
|
153
|
+
* bundle as the main module, whose first import is the adapter (so the
|
|
154
|
+
* adapter has run before any of the Worker's code) and which exports the
|
|
155
|
+
* class check as `classesEntrypoint`, and the adapter. The import shares the
|
|
156
|
+
* bundle's first line, so line numbers stay the bundle's. A Worker with no
|
|
157
|
+
* such binding runs its bundle as it is, and has no class check (null).
|
|
158
|
+
*
|
|
159
|
+
* `classesEntrypoint` is a name the bundle never spells, so it exports no
|
|
160
|
+
* such name itself (a bundler prints an ASCII name as it is).
|
|
161
|
+
*/
|
|
162
|
+
export function innerWorkerModules(bundle, names) {
|
|
163
|
+
if (names.length === 0)
|
|
164
|
+
return { mainModule: MAIN_MODULE, modules: { [MAIN_MODULE]: bundle }, classesEntrypoint: null };
|
|
165
|
+
let classesEntrypoint = CLASSES_ENTRYPOINT;
|
|
166
|
+
for (let n = 2; bundle.includes(classesEntrypoint); n++)
|
|
167
|
+
classesEntrypoint = `${CLASSES_ENTRYPOINT}_${n}`;
|
|
168
|
+
const head = `export { ${CLASSES_ENTRYPOINT} as ${classesEntrypoint} } from './${ADAPTER_MODULE}';`;
|
|
169
|
+
// A hashbang must stay first.
|
|
170
|
+
const at = bundle.startsWith('#!') ? bundle.indexOf('\n') + 1 : 0;
|
|
171
|
+
const main = bundle.slice(0, at) + head + bundle.slice(at);
|
|
172
|
+
const adapter = [
|
|
173
|
+
"import { env, RpcStub, WorkerEntrypoint } from 'cloudflare:workers';",
|
|
174
|
+
`import * as main from './${MAIN_MODULE}';`,
|
|
175
|
+
// The functions below are serialized from the bundled worker, which wraps them in __name.
|
|
176
|
+
ESBUILD_NAME_MODULE_SHIM,
|
|
177
|
+
`const { ${CLASSES_ENTRYPOINT} } = (${innerDoAdapter.toString()})(${innerDoIdFromName.toString()}, ${JSON.stringify(names)}, main, { env, RpcStub, WorkerEntrypoint });`,
|
|
178
|
+
`export { ${CLASSES_ENTRYPOINT} };`,
|
|
179
|
+
].join('\n');
|
|
180
|
+
return { mainModule: MAIN_MODULE, modules: { [MAIN_MODULE]: main, [ADAPTER_MODULE]: adapter }, classesEntrypoint };
|
|
181
|
+
}
|
package/dist/isolate-pool.d.ts
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* running 67 npm tarball extractions (cold-start dominates). We pin
|
|
8
8
|
* each job to `slot = cursor % concurrency` and use stable loader
|
|
9
9
|
* IDs `nfp:${fnHash}:slot-${i}:g${generation}`, so a pool of
|
|
10
|
-
* concurrency=
|
|
10
|
+
* concurrency=N keeps at most N warm isolates rather than one per job.
|
|
11
11
|
* 2. **Nimbus defaults**: compatibilityDate = CF_COMPAT_DATE (matches
|
|
12
|
-
* the supervisor worker), compatibilityFlags =
|
|
12
|
+
* the supervisor worker), compatibilityFlags = GUEST_COMPAT_FLAGS,
|
|
13
13
|
* globalOutbound = undefined (inherit parent network so the facet can
|
|
14
14
|
* reach https://registry.npmjs.org without a proxy binding).
|
|
15
15
|
* 3. **Supervisor autoinjection**. The pool grabs the embedder's
|
|
@@ -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
|
/**
|
|
@@ -44,8 +45,18 @@ export interface IsolatePoolEnv {
|
|
|
44
45
|
}
|
|
45
46
|
/** Options handed to IsolatePool's constructor. */
|
|
46
47
|
export interface IsolatePoolOptions {
|
|
47
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Maximum concurrent in-flight facets, each a distinct Dynamic Worker
|
|
50
|
+
* spent from the hosting DO's `DO_DYNAMIC_WORKER_LIMIT`. Default 1; a
|
|
51
|
+
* caller that wants more sizes it against that budget (Fanout does).
|
|
52
|
+
*/
|
|
48
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;
|
|
49
60
|
/** Per-task timeout in ms. Default 60_000. */
|
|
50
61
|
timeoutMs?: number;
|
|
51
62
|
/**
|
|
@@ -139,15 +150,19 @@ export interface IsolatePoolOptions {
|
|
|
139
150
|
/**
|
|
140
151
|
* WebAssembly modules to ship into the facet via the LOADER's
|
|
141
152
|
* `modules` map. Map keys are module specifier paths (e.g.
|
|
142
|
-
* `'esbuild.wasm'`); values are the raw bytes
|
|
153
|
+
* `'esbuild.wasm'`); values are the raw bytes, or a module the host
|
|
154
|
+
* already holds compiled.
|
|
143
155
|
*
|
|
144
|
-
* Workerd registers each entry as `{ wasm
|
|
145
|
-
*
|
|
156
|
+
* Workerd registers each entry as `{ wasm }` in the worker's modules
|
|
157
|
+
* map. The pool prepends a static
|
|
146
158
|
* `import __NIMBUS_WASM_<id> from './<key>';` to the generated
|
|
147
|
-
* worker.js
|
|
148
|
-
* where wasm code generation is permitted)
|
|
149
|
-
*
|
|
150
|
-
*
|
|
159
|
+
* worker.js; bytes are compiled at the facet's module-load (startup
|
|
160
|
+
* phase, where wasm code generation is permitted), and a compiled
|
|
161
|
+
* module is shared with the facet as is, its compiled code included
|
|
162
|
+
* (workerd src/workerd/api/worker-loader.c++,
|
|
163
|
+
* extractWasmModuleContent). The Modules are exposed via
|
|
164
|
+
* `globalThis.__NIMBUS_WASM[<key>]` for the user function to read at
|
|
165
|
+
* request time.
|
|
151
166
|
*
|
|
152
167
|
* Why this works when other paths don't:
|
|
153
168
|
* - request-time `WebAssembly.compile()` — disallowed by workerd
|
|
@@ -156,15 +171,15 @@ export interface IsolatePoolOptions {
|
|
|
156
171
|
* structured-clone refuses ("Unable to deserialize cloned data").
|
|
157
172
|
* - inlining bytes in the preamble — 16 MiB string per dispatch
|
|
158
173
|
* OOMs the supervisor at module-source allocation time.
|
|
159
|
-
* - LOADER modules-map (this) —
|
|
160
|
-
* blob
|
|
161
|
-
*
|
|
174
|
+
* - LOADER modules-map (this) — the module rides INSIDE the worker
|
|
175
|
+
* code blob, never crossing structured-clone, never executing JS
|
|
176
|
+
* eval.
|
|
162
177
|
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
178
|
+
* A compiled module must be described (host-wasm.ts describeHostWasm):
|
|
179
|
+
* its identity keys warm slots, as the bytes' fingerprint does, and its
|
|
180
|
+
* size counts toward the dynamic-worker code limit.
|
|
166
181
|
*/
|
|
167
|
-
wasmModules?: Record<string, ArrayBuffer>;
|
|
182
|
+
wasmModules?: Record<string, ArrayBuffer | WebAssembly.Module>;
|
|
168
183
|
}
|
|
169
184
|
/** Per-call override (merged with pool defaults). */
|
|
170
185
|
export interface IsolateCallOptions {
|
|
@@ -233,7 +248,7 @@ export declare function assembleLoaderWorkerModuleSource(options: LoaderWorkerMo
|
|
|
233
248
|
* Typical use:
|
|
234
249
|
*
|
|
235
250
|
* const pool = new IsolatePool(env, ctx, {
|
|
236
|
-
* concurrency:
|
|
251
|
+
* concurrency: 2,
|
|
237
252
|
* tag: 'npm-install',
|
|
238
253
|
* });
|
|
239
254
|
* const results = await pool.map(
|
|
@@ -246,6 +261,8 @@ export declare class IsolatePool {
|
|
|
246
261
|
private readonly loader;
|
|
247
262
|
/** The hosting actor, as the loader budget ledger's per-DO key. */
|
|
248
263
|
private readonly ctx;
|
|
264
|
+
/** The width this pool's dispatches are held inside (IsolatePoolOptions.claim). */
|
|
265
|
+
private readonly claim;
|
|
249
266
|
private readonly concurrency;
|
|
250
267
|
private readonly defaultTimeoutMs;
|
|
251
268
|
private readonly defaultRetries;
|
|
@@ -273,11 +290,11 @@ export declare class IsolatePool {
|
|
|
273
290
|
* across pool dispatches (cache-key stability).
|
|
274
291
|
*/
|
|
275
292
|
private readonly wasmModules;
|
|
276
|
-
/** Hash of
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
293
|
+
/** Hash of every constructor-time wasm module, folded into the loader
|
|
294
|
+
* cache key so changes invalidate warm slots: a compiled module by the
|
|
295
|
+
* identity its host described, bytes by name + length + first/last
|
|
296
|
+
* byte. Hashing the FULL bytes would be O(20+ MiB) per dispatch and is
|
|
297
|
+
* unnecessary — they are pinned at deploy time. */
|
|
281
298
|
private readonly wasmHash;
|
|
282
299
|
/**
|
|
283
300
|
* Short prefix of the owning DO's id, baked into the loader.get()
|
|
@@ -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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"}
|