@nimbus-sh/fabric 0.1.0 → 0.2.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 +84 -55
- package/dist/bindings.js +5 -5
- package/dist/budgets.d.ts +132 -0
- package/dist/budgets.d.ts.map +1 -0
- package/dist/budgets.js +248 -0
- package/dist/composition.d.ts +87 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +76 -0
- package/dist/connections.d.ts +81 -0
- package/dist/connections.d.ts.map +1 -0
- package/dist/connections.js +114 -0
- package/dist/derived.d.ts +65 -0
- package/dist/derived.d.ts.map +1 -0
- package/dist/derived.js +95 -0
- package/dist/do-calls.d.ts +94 -0
- package/dist/do-calls.d.ts.map +1 -0
- package/dist/do-calls.js +111 -0
- package/dist/facet-pool.d.ts +90 -0
- package/dist/facet-pool.d.ts.map +1 -0
- package/dist/facet-pool.js +113 -0
- package/dist/{fanout-pool.d.ts → fanout.d.ts} +20 -20
- package/dist/fanout.d.ts.map +1 -0
- package/dist/{fanout-pool.js → fanout.js} +20 -20
- package/dist/{launch-journal.d.ts → fenced-work.d.ts} +25 -13
- package/dist/fenced-work.d.ts.map +1 -0
- package/dist/{launch-journal.js → fenced-work.js} +47 -13
- package/dist/generation.d.ts +69 -0
- package/dist/generation.d.ts.map +1 -0
- package/dist/generation.js +118 -0
- package/dist/{facet-image-store.d.ts → image-store.d.ts} +8 -8
- package/dist/image-store.d.ts.map +1 -0
- package/dist/{facet-image-store.js → image-store.js} +4 -4
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -8
- package/dist/{loader-pool.d.ts → isolate-pool.d.ts} +19 -19
- package/dist/isolate-pool.d.ts.map +1 -0
- package/dist/{loader-pool.js → isolate-pool.js} +20 -20
- package/dist/journal.d.ts +111 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +177 -0
- package/dist/outbox.d.ts +249 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +355 -0
- package/dist/process-fabric.d.ts +2 -14
- package/dist/process-fabric.d.ts.map +1 -1
- package/dist/process-fabric.js +6 -15
- package/dist/process-host.d.ts +1 -1
- package/dist/process-host.d.ts.map +1 -1
- package/dist/process-host.js +10 -9
- package/dist/sealed.d.ts +78 -0
- package/dist/sealed.d.ts.map +1 -0
- package/dist/sealed.js +145 -0
- package/dist/timers.d.ts +138 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +231 -0
- package/dist/{launch-pacer.d.ts → turn-budget.d.ts} +19 -21
- package/dist/turn-budget.d.ts.map +1 -0
- package/dist/{launch-pacer.js → turn-budget.js} +22 -11
- package/dist/workerd-facet-host.d.ts +28 -67
- package/dist/workerd-facet-host.d.ts.map +1 -1
- package/dist/workerd-facet-host.js +49 -171
- package/examples/agent-core-adapter.ts +191 -0
- package/package.json +4 -2
- package/src/bindings.ts +6 -6
- package/src/budgets.ts +308 -0
- package/src/composition.ts +127 -0
- package/src/connections.ts +140 -0
- package/src/derived.ts +135 -0
- package/src/do-calls.ts +156 -0
- package/src/facet-pool.ts +157 -0
- package/src/{fanout-pool.ts → fanout.ts} +35 -35
- package/src/{launch-journal.ts → fenced-work.ts} +58 -22
- package/src/generation.ts +144 -0
- package/src/{facet-image-store.ts → image-store.ts} +9 -9
- package/src/index.ts +16 -8
- package/src/{loader-pool.ts → isolate-pool.ts} +34 -34
- package/src/journal.ts +242 -0
- package/src/node-async-hooks.d.ts +14 -0
- package/src/outbox.ts +520 -0
- package/src/process-fabric.ts +6 -33
- package/src/process-host.ts +10 -15
- package/src/sealed.ts +150 -0
- package/src/timers.ts +294 -0
- package/src/{launch-pacer.ts → turn-budget.ts} +30 -24
- package/src/workerd-facet-host.ts +67 -193
- package/dist/alarms.d.ts +0 -134
- package/dist/alarms.d.ts.map +0 -1
- package/dist/alarms.js +0 -214
- package/dist/ctx-exports.d.ts +0 -47
- package/dist/ctx-exports.d.ts.map +0 -1
- package/dist/ctx-exports.js +0 -54
- package/dist/facet-image-store.d.ts.map +0 -1
- package/dist/fanout-pool.d.ts.map +0 -1
- package/dist/launch-journal.d.ts.map +0 -1
- package/dist/launch-pacer.d.ts.map +0 -1
- package/dist/loader-ledger.d.ts +0 -57
- package/dist/loader-ledger.d.ts.map +0 -1
- package/dist/loader-ledger.js +0 -91
- package/dist/loader-pool.d.ts.map +0 -1
- package/src/alarms.ts +0 -275
- package/src/ctx-exports.ts +0 -77
- package/src/loader-ledger.ts +0 -112
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* generation.ts — the isolate-generation clock, and the deferred
|
|
3
|
+
* reconciliation that runs once per fresh incarnation.
|
|
4
|
+
*
|
|
5
|
+
* Workerd hibernates Durable Objects between requests to free memory. On
|
|
6
|
+
* wake, the new isolate must rebuild its in-memory state from SQL — but it
|
|
7
|
+
* also needs to know "is this the same lifecycle as before, or did workerd
|
|
8
|
+
* recycle me?" That distinction matters for recovery (warmJoin vs cold init)
|
|
9
|
+
* and is captured by the isolate generation, a counter persisted across
|
|
10
|
+
* hibernations.
|
|
11
|
+
*
|
|
12
|
+
* State is keyed weakly off the actor's `ctx`, which lives exactly as long as
|
|
13
|
+
* the incarnation: a fresh isolate gets a fresh `ctx`, adopts the persisted
|
|
14
|
+
* counter, and bumps it once. The embedder reads `generation(ctx)` wherever it
|
|
15
|
+
* needs the incarnation number — one source of truth instead of mirrored host
|
|
16
|
+
* fields.
|
|
17
|
+
*/
|
|
18
|
+
import { errorText } from '@nimbus-sh/core/_shared/error-text.js';
|
|
19
|
+
/**
|
|
20
|
+
* Storage key for the isolate-generation counter (cold-start +
|
|
21
|
+
* post-hibernation wake; one increment per fresh isolate).
|
|
22
|
+
*
|
|
23
|
+
* The VALUE is live production DO storage ('w9_isolate_gen') and must never
|
|
24
|
+
* change — renaming a storage key is a migration, and orphaned rows are the
|
|
25
|
+
* least of what it breaks.
|
|
26
|
+
*/
|
|
27
|
+
export const GENERATION_KEY = 'w9_isolate_gen';
|
|
28
|
+
const states = new WeakMap();
|
|
29
|
+
function stateOf(ctx) {
|
|
30
|
+
let state = states.get(ctx);
|
|
31
|
+
if (!state) {
|
|
32
|
+
state = { value: 0, adopted: false, coldStart: [], coldStartChain: Promise.resolve() };
|
|
33
|
+
states.set(ctx, state);
|
|
34
|
+
}
|
|
35
|
+
return state;
|
|
36
|
+
}
|
|
37
|
+
/** This incarnation's generation. Zero until {@link adoptGeneration} ran. */
|
|
38
|
+
export function generation(ctx) {
|
|
39
|
+
return states.get(ctx)?.value ?? 0;
|
|
40
|
+
}
|
|
41
|
+
/** Increment + persist the generation counter once per fresh isolate. */
|
|
42
|
+
export async function adoptGeneration(ctx) {
|
|
43
|
+
const state = stateOf(ctx);
|
|
44
|
+
if (state.adopted)
|
|
45
|
+
return;
|
|
46
|
+
state.adopted = true;
|
|
47
|
+
try {
|
|
48
|
+
const prev = (await ctx.storage.get(GENERATION_KEY));
|
|
49
|
+
// Adopt the persisted truth first, and adopt the bump only after the
|
|
50
|
+
// put resolves. An unpersisted `next` would be re-read as `prev` by the
|
|
51
|
+
// NEXT boot and re-issued — two instances sharing one generation is
|
|
52
|
+
// exactly the pid-aliasing this counter exists to prevent. Running on
|
|
53
|
+
// the previous persisted generation is the lesser lapse, and the
|
|
54
|
+
// put-failure case is replica-only in practice (replicas never spawn).
|
|
55
|
+
//
|
|
56
|
+
// What holds the guarantee is the output gate, not this await: measured,
|
|
57
|
+
// the block body resolves in 0 ms even with a confirmed put, because
|
|
58
|
+
// `await storage.put()` returns before durability. The gate is what
|
|
59
|
+
// keeps a pid from generation N from escaping before N is durable, which
|
|
60
|
+
// is why marking this put `allowUnconfirmed` is not a free speedup — see
|
|
61
|
+
// scratchpad/coldstart-s1.md.
|
|
62
|
+
state.value = typeof prev === 'number' ? prev : 0;
|
|
63
|
+
const next = state.value + 1;
|
|
64
|
+
await ctx.storage.put(GENERATION_KEY, next);
|
|
65
|
+
state.value = next;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
console.warn('[nimbus/W9] generation bump failed:', errorText(e));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Take on a generation without persisting it, and clear the adopted guard so
|
|
73
|
+
* a later {@link adoptGeneration} re-derives from storage. The
|
|
74
|
+
* destroy-and-recreate path uses this: it wipes storage, re-persists the
|
|
75
|
+
* pre-destroy counter, and runs the rest of this incarnation on the successor
|
|
76
|
+
* generation the next boot will derive.
|
|
77
|
+
*/
|
|
78
|
+
export function assumeGeneration(ctx, value) {
|
|
79
|
+
const state = stateOf(ctx);
|
|
80
|
+
state.value = value;
|
|
81
|
+
state.adopted = false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Queue deferred async reconciliation for this incarnation.
|
|
85
|
+
*
|
|
86
|
+
* The task runs on the first {@link runColdStart} after registration — a turn
|
|
87
|
+
* the embedder already owns, NEVER the constructor's init gate. Awaiting
|
|
88
|
+
* recovery on the gate path is the trap this helper exists to avoid: the gate
|
|
89
|
+
* blocks every request to the object, and reconciliation wants a filesystem
|
|
90
|
+
* and a terminal that only a later turn has. The gate is also a wall, not
|
|
91
|
+
* just a stall: a `blockConcurrencyWhile` callback still pending at ~30 s
|
|
92
|
+
* (BLOCK_CONCURRENCY_CANCEL_MS, proven by probe) is cancelled and RESETS the
|
|
93
|
+
* object with every queued event — so never call {@link runColdStart} from
|
|
94
|
+
* inside one; the pump and the embedder's own turns are the places it runs.
|
|
95
|
+
*/
|
|
96
|
+
export function onColdStart(ctx, task) {
|
|
97
|
+
stateOf(ctx).coldStart.push(task);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Drain the queued cold-start tasks, serialized, each awaited so the turn
|
|
101
|
+
* that runs them pays for them. Idempotent between registrations: a drained
|
|
102
|
+
* queue is a cheap no-op, and a task registered after a drain runs on the
|
|
103
|
+
* next call.
|
|
104
|
+
*/
|
|
105
|
+
export function runColdStart(ctx) {
|
|
106
|
+
const state = stateOf(ctx);
|
|
107
|
+
if (state.coldStart.length === 0)
|
|
108
|
+
return state.coldStartChain;
|
|
109
|
+
const tasks = state.coldStart;
|
|
110
|
+
state.coldStart = [];
|
|
111
|
+
const chained = state.coldStartChain.then(async () => {
|
|
112
|
+
for (const task of tasks) {
|
|
113
|
+
await task();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
state.coldStartChain = chained.catch(() => { });
|
|
117
|
+
return chained;
|
|
118
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* image-store.ts — materializing resident-process boot images into the
|
|
3
3
|
* content-addressed image store, and sweeping the ones nothing boots from.
|
|
4
4
|
*
|
|
5
5
|
* A resident process's module map is sized by the user's disk, so it does not
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* table.
|
|
13
13
|
*
|
|
14
14
|
* The filesystem itself stays the embedder's, reached through the
|
|
15
|
-
* {@link
|
|
15
|
+
* {@link ImageBlobStore} port — the store decides what is written where
|
|
16
16
|
* and when; the port decides how bytes land on a disk and with what modes and
|
|
17
17
|
* credentials.
|
|
18
18
|
*/
|
|
19
|
-
import type {
|
|
19
|
+
import type { TurnBudget } from './turn-budget.js';
|
|
20
20
|
/**
|
|
21
21
|
* Bytes of an image written in one storage transaction.
|
|
22
22
|
*
|
|
@@ -34,7 +34,7 @@ export declare const FACET_IMAGE_WRITE_SLICE_BYTES: number;
|
|
|
34
34
|
* normalization are the implementation's: the store passes the same
|
|
35
35
|
* store-relative paths it later roots and sweeps by.
|
|
36
36
|
*/
|
|
37
|
-
export interface
|
|
37
|
+
export interface ImageBlobStore {
|
|
38
38
|
/** Create a directory (and its parents) if it does not exist. */
|
|
39
39
|
mkdirp(dir: string): void;
|
|
40
40
|
/** The file's current size in bytes, or null when it does not exist. */
|
|
@@ -56,7 +56,7 @@ export interface FacetImageBlobStore {
|
|
|
56
56
|
* hash's problem; everything else is idempotent — an image already present
|
|
57
57
|
* at its own digest is already the bytes we were about to write.
|
|
58
58
|
*/
|
|
59
|
-
export declare class
|
|
59
|
+
export declare class ImageStore {
|
|
60
60
|
private readonly blobs;
|
|
61
61
|
private readonly isLive;
|
|
62
62
|
/** pid → the boot images its facet loads from; the image sweep's root set. */
|
|
@@ -69,7 +69,7 @@ export declare class FacetImageStore {
|
|
|
69
69
|
* @param isLive Whether a pid still names a running process. The root set
|
|
70
70
|
* is the process table, reached through this one predicate.
|
|
71
71
|
*/
|
|
72
|
-
constructor(blobs: () =>
|
|
72
|
+
constructor(blobs: () => ImageBlobStore, isLive: (pid: number) => boolean);
|
|
73
73
|
/**
|
|
74
74
|
* The image store's directory, created before the first filesystem view is
|
|
75
75
|
* built rather than on the first image write.
|
|
@@ -95,7 +95,7 @@ export declare class FacetImageStore {
|
|
|
95
95
|
* Writing the sources here, once, is what lets the session stop holding
|
|
96
96
|
* them: after this returns, the only thing it keeps is a path.
|
|
97
97
|
*/
|
|
98
|
-
materialize(pid: number, modules: Record<string, string>, pacer:
|
|
98
|
+
materialize(pid: number, modules: Record<string, string>, pacer: TurnBudget): Promise<Record<string, string>>;
|
|
99
99
|
/**
|
|
100
100
|
* Drop every image no running process boots from.
|
|
101
101
|
*
|
|
@@ -109,4 +109,4 @@ export declare class FacetImageStore {
|
|
|
109
109
|
*/
|
|
110
110
|
private sweep;
|
|
111
111
|
}
|
|
112
|
-
//# sourceMappingURL=
|
|
112
|
+
//# sourceMappingURL=image-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-store.d.ts","sourceRoot":"","sources":["../src/image-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,QAA0D,CAAC;AAErG;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wEAAwE;IACxE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,wEAAwE;IACxE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACjD,kDAAkD;IAClD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAClE,2EAA2E;IAC3E,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B,qDAAqD;IACrD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,qBAAa,UAAU;IAanB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,8EAA8E;IAC9E,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;OAMG;gBAEgB,KAAK,EAAE,MAAM,cAAc,EAC3B,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO;IAGnD;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,IAAI,IAAI;IAOjB;;;;;;OAMG;IACG,WAAW,CACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAoDlC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,KAAK;CAgBd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* image-store.ts — materializing resident-process boot images into the
|
|
3
3
|
* content-addressed image store, and sweeping the ones nothing boots from.
|
|
4
4
|
*
|
|
5
5
|
* A resident process's module map is sized by the user's disk, so it does not
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
* table.
|
|
13
13
|
*
|
|
14
14
|
* The filesystem itself stays the embedder's, reached through the
|
|
15
|
-
* {@link
|
|
15
|
+
* {@link ImageBlobStore} port — the store decides what is written where
|
|
16
16
|
* and when; the port decides how bytes land on a disk and with what modes and
|
|
17
17
|
* credentials.
|
|
18
18
|
*/
|
|
19
|
-
import { MAX_TX_BLOB_BYTES, CHUNK_SIZE } from '@nimbus-sh/
|
|
19
|
+
import { MAX_TX_BLOB_BYTES, CHUNK_SIZE } from '@nimbus-sh/platform/limits.js';
|
|
20
20
|
import { FACET_IMAGE_DIR, facetImageDigest, facetImagePath } from './process-fabric.js';
|
|
21
21
|
/**
|
|
22
22
|
* Bytes of an image written in one storage transaction.
|
|
@@ -37,7 +37,7 @@ export const FACET_IMAGE_WRITE_SLICE_BYTES = Math.floor(MAX_TX_BLOB_BYTES / CHUN
|
|
|
37
37
|
* hash's problem; everything else is idempotent — an image already present
|
|
38
38
|
* at its own digest is already the bytes we were about to write.
|
|
39
39
|
*/
|
|
40
|
-
export class
|
|
40
|
+
export class ImageStore {
|
|
41
41
|
blobs;
|
|
42
42
|
isLive;
|
|
43
43
|
/** pid → the boot images its facet loads from; the image sweep's root set. */
|
package/dist/index.d.ts
CHANGED
|
@@ -6,16 +6,24 @@
|
|
|
6
6
|
* at resolution; non-workerd consumers (tests, tooling) import the subpath
|
|
7
7
|
* modules they need instead.
|
|
8
8
|
*/
|
|
9
|
-
export * from './
|
|
9
|
+
export * from './generation.js';
|
|
10
|
+
export * from './timers.js';
|
|
11
|
+
export * from './outbox.js';
|
|
12
|
+
export * from './journal.js';
|
|
13
|
+
export * from './do-calls.js';
|
|
14
|
+
export * from './facet-pool.js';
|
|
15
|
+
export * from './derived.js';
|
|
16
|
+
export * from './connections.js';
|
|
17
|
+
export * from './sealed.js';
|
|
10
18
|
export * from './bindings.js';
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './fanout
|
|
19
|
+
export * from './composition.js';
|
|
20
|
+
export * from './image-store.js';
|
|
21
|
+
export * from './fanout.js';
|
|
14
22
|
export * from './inner-do-registry.js';
|
|
15
|
-
export * from './
|
|
16
|
-
export * from './
|
|
17
|
-
export * from './
|
|
18
|
-
export * from './
|
|
23
|
+
export * from './fenced-work.js';
|
|
24
|
+
export * from './turn-budget.js';
|
|
25
|
+
export * from './budgets.js';
|
|
26
|
+
export * from './isolate-pool.js';
|
|
19
27
|
export * from './process-fabric.js';
|
|
20
28
|
export * from './process-host.js';
|
|
21
29
|
export * from './workerd-facet-host.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,24 @@
|
|
|
6
6
|
* at resolution; non-workerd consumers (tests, tooling) import the subpath
|
|
7
7
|
* modules they need instead.
|
|
8
8
|
*/
|
|
9
|
-
export * from './
|
|
9
|
+
export * from './generation.js';
|
|
10
|
+
export * from './timers.js';
|
|
11
|
+
export * from './outbox.js';
|
|
12
|
+
export * from './journal.js';
|
|
13
|
+
export * from './do-calls.js';
|
|
14
|
+
export * from './facet-pool.js';
|
|
15
|
+
export * from './derived.js';
|
|
16
|
+
export * from './connections.js';
|
|
17
|
+
export * from './sealed.js';
|
|
10
18
|
export * from './bindings.js';
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './fanout
|
|
19
|
+
export * from './composition.js';
|
|
20
|
+
export * from './image-store.js';
|
|
21
|
+
export * from './fanout.js';
|
|
14
22
|
export * from './inner-do-registry.js';
|
|
15
|
-
export * from './
|
|
16
|
-
export * from './
|
|
17
|
-
export * from './
|
|
18
|
-
export * from './
|
|
23
|
+
export * from './fenced-work.js';
|
|
24
|
+
export * from './turn-budget.js';
|
|
25
|
+
export * from './budgets.js';
|
|
26
|
+
export * from './isolate-pool.js';
|
|
19
27
|
export * from './process-fabric.js';
|
|
20
28
|
export * from './process-host.js';
|
|
21
29
|
export * from './workerd-facet-host.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* isolate-pool.ts — Nimbus loader-isolate pool based on cloudflare-parallel.
|
|
3
3
|
*
|
|
4
4
|
* Adds Nimbus-specific behavior to the upstream pool design:
|
|
5
5
|
* 1. **Stable-slot isolate reuse**. Upstream's #counter++ gives every
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* reach https://registry.npmjs.org without a proxy binding).
|
|
15
15
|
* 3. **Supervisor autoinjection**. The pool grabs the embedder's
|
|
16
16
|
* registered supervisor entrypoint stub (see `supervisorEntrypoint` in
|
|
17
|
-
*
|
|
17
|
+
* composition.ts) and forwards it as `env.SUPERVISOR` to every facet,
|
|
18
18
|
* same pattern as git-network-facet.ts. Callers can add more bindings
|
|
19
19
|
* via `extraBindings`.
|
|
20
20
|
* 4. **Fail-loud defaults**: timeout 60s, retries 0, onError 'throw'.
|
|
@@ -38,11 +38,11 @@ export type FacetTaskFn<A, R> = {
|
|
|
38
38
|
task(args: A, env: FacetBindings): R | Promise<R>;
|
|
39
39
|
}['task'];
|
|
40
40
|
/** The one binding a pool needs off whichever env its host hands it. */
|
|
41
|
-
export interface
|
|
41
|
+
export interface IsolatePoolEnv {
|
|
42
42
|
LOADER?: WorkerLoader;
|
|
43
43
|
}
|
|
44
|
-
/** Options handed to
|
|
45
|
-
export interface
|
|
44
|
+
/** Options handed to IsolatePool's constructor. */
|
|
45
|
+
export interface IsolatePoolOptions {
|
|
46
46
|
/** Maximum concurrent in-flight facets. Default 4. */
|
|
47
47
|
concurrency?: number;
|
|
48
48
|
/** Per-task timeout in ms. Default 60_000. */
|
|
@@ -79,8 +79,8 @@ export interface LoaderPoolOptions {
|
|
|
79
79
|
* Override the `doId` baked into the auto-injected SUPERVISOR binding.
|
|
80
80
|
* Default: `ctx.id.toString()` (the DO that constructs the pool).
|
|
81
81
|
*
|
|
82
|
-
* Used by
|
|
83
|
-
* construct their per-task
|
|
82
|
+
* Used by Fanout's peer-DO branch (peer-DO fanout): peer DOs
|
|
83
|
+
* construct their per-task IsolatePool from inside
|
|
84
84
|
* `_rpcFanoutExecute`, where `ctx` is the PEER DO's ctx. Without this
|
|
85
85
|
* override the peer's auto-injected SUPERVISOR routes back to the
|
|
86
86
|
* peer DO itself — so writes (e.g. install-batch-facet's
|
|
@@ -151,7 +151,7 @@ export interface LoaderPoolOptions {
|
|
|
151
151
|
wasmModules?: Record<string, ArrayBuffer>;
|
|
152
152
|
}
|
|
153
153
|
/** Per-call override (merged with pool defaults). */
|
|
154
|
-
export interface
|
|
154
|
+
export interface IsolateCallOptions {
|
|
155
155
|
timeoutMs?: number;
|
|
156
156
|
retries?: number;
|
|
157
157
|
/**
|
|
@@ -186,7 +186,7 @@ export interface LoaderCallOptions {
|
|
|
186
186
|
wasmModules?: Record<string, ArrayBuffer>;
|
|
187
187
|
}
|
|
188
188
|
/** Per-map override. Adds onError strategy for partial failures. */
|
|
189
|
-
export interface
|
|
189
|
+
export interface IsolateMapOptions extends IsolateCallOptions {
|
|
190
190
|
/** Concurrency override for this call. Defaults to pool's concurrency. */
|
|
191
191
|
concurrency?: number;
|
|
192
192
|
/**
|
|
@@ -216,7 +216,7 @@ export declare function assembleLoaderWorkerModuleSource(options: LoaderWorkerMo
|
|
|
216
216
|
*
|
|
217
217
|
* Typical use:
|
|
218
218
|
*
|
|
219
|
-
* const pool = new
|
|
219
|
+
* const pool = new IsolatePool(env, ctx, {
|
|
220
220
|
* concurrency: 4,
|
|
221
221
|
* tag: 'npm-install',
|
|
222
222
|
* });
|
|
@@ -225,10 +225,10 @@ export declare function assembleLoaderWorkerModuleSource(options: LoaderWorkerMo
|
|
|
225
225
|
* toFetch,
|
|
226
226
|
* );
|
|
227
227
|
*/
|
|
228
|
-
export declare class
|
|
228
|
+
export declare class IsolatePool {
|
|
229
229
|
#private;
|
|
230
230
|
private readonly loader;
|
|
231
|
-
/** The hosting actor, as the loader
|
|
231
|
+
/** The hosting actor, as the loader budget ledger's per-DO key. */
|
|
232
232
|
private readonly ctx;
|
|
233
233
|
private readonly concurrency;
|
|
234
234
|
private readonly defaultTimeoutMs;
|
|
@@ -240,7 +240,7 @@ export declare class LoaderPool {
|
|
|
240
240
|
private readonly preambleHash;
|
|
241
241
|
/**
|
|
242
242
|
* WASM modules to ship in the LOADER `modules` map. See
|
|
243
|
-
*
|
|
243
|
+
* IsolatePoolOptions.wasmModules for the rationale. Stored in
|
|
244
244
|
* insertion order so the per-import preamble we generate matches
|
|
245
245
|
* across pool dispatches (cache-key stability).
|
|
246
246
|
*/
|
|
@@ -262,25 +262,25 @@ export declare class LoaderPool {
|
|
|
262
262
|
* 12 chars is enough entropy for DO ids to collide-free per process.
|
|
263
263
|
*/
|
|
264
264
|
private readonly doIdShort;
|
|
265
|
-
constructor(env: unknown, ctx: DurableObjectState, opts?:
|
|
265
|
+
constructor(env: unknown, ctx: DurableObjectState, opts?: IsolatePoolOptions);
|
|
266
266
|
/** Effective concurrency used when no per-call override is supplied. */
|
|
267
267
|
get defaultConcurrency(): number;
|
|
268
268
|
/**
|
|
269
269
|
* Run `fn` once with `arg` on a slot isolate. Returns the result or
|
|
270
270
|
* throws TimeoutError / RetryExhaustedError / ExecutionError.
|
|
271
271
|
*/
|
|
272
|
-
submit<T, R>(fn: FacetTaskFn<T, R>, arg: T, opts?:
|
|
272
|
+
submit<T, R>(fn: FacetTaskFn<T, R>, arg: T, opts?: IsolateCallOptions): Promise<Awaited<R>>;
|
|
273
273
|
/**
|
|
274
274
|
* Run `fn` on every item in `items`, at most `concurrency` at a time,
|
|
275
275
|
* pinned to stable slots so warm isolates are reused.
|
|
276
276
|
*
|
|
277
277
|
* Results are returned in input order. Failure handling per `onError`.
|
|
278
278
|
*/
|
|
279
|
-
map<T, R>(fn: FacetTaskFn<T, R>, items: T[], opts?:
|
|
279
|
+
map<T, R>(fn: FacetTaskFn<T, R>, items: T[], opts?: IsolateMapOptions): Promise<Array<Awaited<R> | null>>;
|
|
280
280
|
/**
|
|
281
281
|
* Same shape as `map`, but accepts a pre-serialized function source
|
|
282
282
|
* string instead of a live function reference. Used by
|
|
283
|
-
* `
|
|
283
|
+
* `Fanout`'s peer-DO leg, where the function was already
|
|
284
284
|
* serialized on the coordinator side and forwarded over RPC.
|
|
285
285
|
*
|
|
286
286
|
* The fnSource MUST be the output of `serializeFunction(fn)`
|
|
@@ -294,7 +294,7 @@ export declare class LoaderPool {
|
|
|
294
294
|
* No fn-validation runs here (it already ran on the coordinator);
|
|
295
295
|
* the peer trusts the caller to forward a valid serialization.
|
|
296
296
|
*/
|
|
297
|
-
mapSource<T, R>(fnSource: string, items: T[], opts?:
|
|
297
|
+
mapSource<T, R>(fnSource: string, items: T[], opts?: IsolateMapOptions): Promise<Array<Awaited<R> | null>>;
|
|
298
298
|
/**
|
|
299
299
|
* Release any RPC stubs held by the pool. Call this once the caller
|
|
300
300
|
* is done with the pool (post-`map`/`submit`) so the underlying
|
|
@@ -312,4 +312,4 @@ export declare class LoaderPool {
|
|
|
312
312
|
*/
|
|
313
313
|
dispose(): void;
|
|
314
314
|
}
|
|
315
|
-
//# sourceMappingURL=
|
|
315
|
+
//# sourceMappingURL=isolate-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isolate-pool.d.ts","sourceRoot":"","sources":["../src/isolate-pool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* isolate-pool.ts — Nimbus loader-isolate pool based on cloudflare-parallel.
|
|
3
3
|
*
|
|
4
4
|
* Adds Nimbus-specific behavior to the upstream pool design:
|
|
5
5
|
* 1. **Stable-slot isolate reuse**. Upstream's #counter++ gives every
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* reach https://registry.npmjs.org without a proxy binding).
|
|
15
15
|
* 3. **Supervisor autoinjection**. The pool grabs the embedder's
|
|
16
16
|
* registered supervisor entrypoint stub (see `supervisorEntrypoint` in
|
|
17
|
-
*
|
|
17
|
+
* composition.ts) and forwards it as `env.SUPERVISOR` to every facet,
|
|
18
18
|
* same pattern as git-network-facet.ts. Callers can add more bindings
|
|
19
19
|
* via `extraBindings`.
|
|
20
20
|
* 4. **Fail-loud defaults**: timeout 60s, retries 0, onError 'throw'.
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
* and binding types used by this implementation.
|
|
25
25
|
*/
|
|
26
26
|
import { CF_COMPAT_DATE } from '@nimbus-sh/core/constants.js';
|
|
27
|
-
import { supervisorEntrypoint } from './
|
|
28
|
-
import { disposeRpcResource } from '@nimbus-sh/
|
|
27
|
+
import { supervisorEntrypoint } from './composition.js';
|
|
28
|
+
import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
|
|
29
29
|
import { serializeFunction, hashSource } from './vendor/serialize.js';
|
|
30
|
-
import { beginLoaderFetch, recordLoaderId, withDynamicWorkerCapNamed } from './
|
|
31
|
-
import { assertModuleMapWithinCodeLimit } from './
|
|
32
|
-
import { recordFailure, setLastFacetId, getLastRpcFrame } from '@nimbus-sh/
|
|
33
|
-
import { classifyError } from '@nimbus-sh/
|
|
30
|
+
import { beginLoaderFetch, recordLoaderId, withDynamicWorkerCapNamed } from './budgets.js';
|
|
31
|
+
import { assertModuleMapWithinCodeLimit } from './budgets.js';
|
|
32
|
+
import { recordFailure, setLastFacetId, getLastRpcFrame } from '@nimbus-sh/platform/oom-discriminator.js';
|
|
33
|
+
import { classifyError } from '@nimbus-sh/platform/oom-classify.js';
|
|
34
34
|
import { BindingError, ExecutionError, RetryExhaustedError, TimeoutError, } from './vendor/errors.js';
|
|
35
35
|
/**
|
|
36
36
|
* esbuild runtime helpers re-declared at the top of every generated facet
|
|
@@ -95,7 +95,7 @@ export function assembleLoaderWorkerModuleSource(options) {
|
|
|
95
95
|
*
|
|
96
96
|
* Typical use:
|
|
97
97
|
*
|
|
98
|
-
* const pool = new
|
|
98
|
+
* const pool = new IsolatePool(env, ctx, {
|
|
99
99
|
* concurrency: 4,
|
|
100
100
|
* tag: 'npm-install',
|
|
101
101
|
* });
|
|
@@ -104,9 +104,9 @@ export function assembleLoaderWorkerModuleSource(options) {
|
|
|
104
104
|
* toFetch,
|
|
105
105
|
* );
|
|
106
106
|
*/
|
|
107
|
-
export class
|
|
107
|
+
export class IsolatePool {
|
|
108
108
|
loader;
|
|
109
|
-
/** The hosting actor, as the loader
|
|
109
|
+
/** The hosting actor, as the loader budget ledger's per-DO key. */
|
|
110
110
|
ctx;
|
|
111
111
|
concurrency;
|
|
112
112
|
defaultTimeoutMs;
|
|
@@ -118,7 +118,7 @@ export class LoaderPool {
|
|
|
118
118
|
preambleHash;
|
|
119
119
|
/**
|
|
120
120
|
* WASM modules to ship in the LOADER `modules` map. See
|
|
121
|
-
*
|
|
121
|
+
* IsolatePoolOptions.wasmModules for the rationale. Stored in
|
|
122
122
|
* insertion order so the per-import preamble we generate matches
|
|
123
123
|
* across pool dispatches (cache-key stability).
|
|
124
124
|
*/
|
|
@@ -145,7 +145,7 @@ export class LoaderPool {
|
|
|
145
145
|
// claim is checked on the next line.
|
|
146
146
|
const loader = env?.LOADER;
|
|
147
147
|
if (!loader || typeof loader.get !== 'function') {
|
|
148
|
-
throw new BindingError('
|
|
148
|
+
throw new BindingError('IsolatePool: env.LOADER binding missing or invalid. ' +
|
|
149
149
|
'Add a [[worker_loaders]] entry to wrangler.jsonc.');
|
|
150
150
|
}
|
|
151
151
|
this.loader = loader;
|
|
@@ -174,12 +174,12 @@ export class LoaderPool {
|
|
|
174
174
|
// Reached only when a caller broke the declared option type, so the
|
|
175
175
|
// value is whatever it really was rather than the ArrayBuffer here.
|
|
176
176
|
const got = bytes?.constructor?.name;
|
|
177
|
-
throw new BindingError(`
|
|
177
|
+
throw new BindingError(`IsolatePool: wasmModules['${name}'] must be ArrayBuffer ` +
|
|
178
178
|
`(got ${got || typeof bytes}).`);
|
|
179
179
|
}
|
|
180
180
|
const id = name.replace(/[^A-Za-z0-9_]/g, '_').replace(/^[^A-Za-z_]/, '_');
|
|
181
181
|
if (seenIds.has(id)) {
|
|
182
|
-
throw new BindingError(`
|
|
182
|
+
throw new BindingError(`IsolatePool: wasmModules key '${name}' collides with another after ` +
|
|
183
183
|
`identifier-sanitisation (id='${id}'). Pick distinct module names.`);
|
|
184
184
|
}
|
|
185
185
|
seenIds.add(id);
|
|
@@ -259,17 +259,17 @@ export class LoaderPool {
|
|
|
259
259
|
for (const [name, bytes] of Object.entries(perCall)) {
|
|
260
260
|
if (!(bytes instanceof ArrayBuffer)) {
|
|
261
261
|
const got = bytes?.constructor?.name;
|
|
262
|
-
throw new BindingError(`
|
|
262
|
+
throw new BindingError(`IsolatePool: per-call wasmModules['${name}'] must be ` +
|
|
263
263
|
`ArrayBuffer (got ${got || typeof bytes}).`);
|
|
264
264
|
}
|
|
265
265
|
const id = name.replace(/[^A-Za-z0-9_]/g, '_').replace(/^[^A-Za-z_]/, '_');
|
|
266
266
|
if (ctorIds.has(id)) {
|
|
267
|
-
throw new BindingError(`
|
|
267
|
+
throw new BindingError(`IsolatePool: per-call wasmModules key '${name}' (sanitised ` +
|
|
268
268
|
`id='${id}') collides with a constructor-time wasm module. ` +
|
|
269
269
|
`Per-call modules cannot shadow pool-defaults. Pick a distinct name.`);
|
|
270
270
|
}
|
|
271
271
|
if (seen.has(id)) {
|
|
272
|
-
throw new BindingError(`
|
|
272
|
+
throw new BindingError(`IsolatePool: per-call wasmModules key '${name}' (sanitised ` +
|
|
273
273
|
`id='${id}') collides with another per-call key. Pick distinct names.`);
|
|
274
274
|
}
|
|
275
275
|
seen.add(id);
|
|
@@ -352,7 +352,7 @@ export class LoaderPool {
|
|
|
352
352
|
// re-import (the user fn is serialized via fn.toString and doesn't
|
|
353
353
|
// carry import statements).
|
|
354
354
|
//
|
|
355
|
-
// Per-call entries (passed via
|
|
355
|
+
// Per-call entries (passed via IsolateCallOptions.wasmModules
|
|
356
356
|
// — used by the wasm-runner shell command) are appended to the same
|
|
357
357
|
// table. Naming collision with constructor entries is rejected
|
|
358
358
|
// upstream in #materialisePerCallWasm so the import block here
|
|
@@ -584,7 +584,7 @@ export class LoaderPool {
|
|
|
584
584
|
/**
|
|
585
585
|
* Same shape as `map`, but accepts a pre-serialized function source
|
|
586
586
|
* string instead of a live function reference. Used by
|
|
587
|
-
* `
|
|
587
|
+
* `Fanout`'s peer-DO leg, where the function was already
|
|
588
588
|
* serialized on the coordinator side and forwarded over RPC.
|
|
589
589
|
*
|
|
590
590
|
* The fnSource MUST be the output of `serializeFunction(fn)`
|