@nimbus-sh/fabric 0.7.1 → 0.9.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.
Files changed (66) hide show
  1. package/README.md +26 -11
  2. package/dist/bindings.d.ts +1 -0
  3. package/dist/bindings.d.ts.map +1 -1
  4. package/dist/bindings.js +2 -0
  5. package/dist/budgets.d.ts +50 -29
  6. package/dist/budgets.d.ts.map +1 -1
  7. package/dist/budgets.js +88 -40
  8. package/dist/connections.d.ts +1 -1
  9. package/dist/connections.js +1 -1
  10. package/dist/do-calls.d.ts +91 -9
  11. package/dist/do-calls.d.ts.map +1 -1
  12. package/dist/do-calls.js +161 -22
  13. package/dist/facet-pool.d.ts +3 -0
  14. package/dist/facet-pool.d.ts.map +1 -1
  15. package/dist/facet-pool.js +3 -0
  16. package/dist/fanout.d.ts +40 -32
  17. package/dist/fanout.d.ts.map +1 -1
  18. package/dist/fanout.js +50 -53
  19. package/dist/fenced-work.d.ts +3 -3
  20. package/dist/host-wasm.d.ts +29 -0
  21. package/dist/host-wasm.d.ts.map +1 -0
  22. package/dist/host-wasm.js +31 -0
  23. package/dist/image-store.d.ts +1 -1
  24. package/dist/image-store.d.ts.map +1 -1
  25. package/dist/image-store.js +34 -2
  26. package/dist/inner-do-registry.d.ts +9 -0
  27. package/dist/inner-do-registry.d.ts.map +1 -1
  28. package/dist/inner-do-registry.js +35 -0
  29. package/dist/isolate-pool.d.ts +32 -24
  30. package/dist/isolate-pool.d.ts.map +1 -1
  31. package/dist/isolate-pool.js +78 -54
  32. package/dist/process-fabric.d.ts +42 -23
  33. package/dist/process-fabric.d.ts.map +1 -1
  34. package/dist/process-fabric.js +62 -6
  35. package/dist/process-host.d.ts +3 -1
  36. package/dist/process-host.d.ts.map +1 -1
  37. package/dist/process-host.js +13 -14
  38. package/dist/supervisor-props.d.ts +47 -0
  39. package/dist/supervisor-props.d.ts.map +1 -0
  40. package/dist/supervisor-props.js +37 -0
  41. package/dist/timers.d.ts +12 -0
  42. package/dist/timers.d.ts.map +1 -1
  43. package/dist/timers.js +44 -9
  44. package/dist/vendor/types.d.ts +11 -5
  45. package/dist/vendor/types.d.ts.map +1 -1
  46. package/dist/workerd-facet-host.d.ts +4 -17
  47. package/dist/workerd-facet-host.d.ts.map +1 -1
  48. package/dist/workerd-facet-host.js +120 -54
  49. package/package.json +6 -6
  50. package/src/bindings.ts +2 -0
  51. package/src/budgets.ts +96 -49
  52. package/src/connections.ts +1 -1
  53. package/src/do-calls.ts +216 -25
  54. package/src/facet-pool.ts +5 -0
  55. package/src/fanout.ts +64 -56
  56. package/src/fenced-work.ts +3 -3
  57. package/src/host-wasm.ts +41 -0
  58. package/src/image-store.ts +30 -3
  59. package/src/inner-do-registry.ts +31 -0
  60. package/src/isolate-pool.ts +108 -74
  61. package/src/process-fabric.ts +88 -30
  62. package/src/process-host.ts +16 -14
  63. package/src/supervisor-props.ts +56 -0
  64. package/src/timers.ts +45 -9
  65. package/src/vendor/types.ts +11 -5
  66. package/src/workerd-facet-host.ts +123 -58
@@ -17,13 +17,19 @@ export interface JsonModule {
17
17
  json: unknown;
18
18
  }
19
19
  /**
20
- * A compiled WebAssembly module, importable from a facet by module name.
21
- * Nimbus ships these on every path — sql.js for node:sqlite, the interpreter
22
- * images for python and ruby — so the omission here was the type lagging the
23
- * API, not a kind the loader lacks.
20
+ * A WebAssembly module, importable from a facet by module name. Nimbus ships
21
+ * these on every path — sql.js for node:sqlite, the interpreter images for
22
+ * python and ruby — so the omission here was the type lagging the API, not a
23
+ * kind the loader lacks. The loader takes either the bytes, which it
24
+ * compiles, or a module the caller holds compiled already, whose compiled
25
+ * code the dynamic worker then shares (workerd src/workerd/api/
26
+ * worker-loader.c++, extractWasmModuleContent). A module handed over this
27
+ * way should be described with describeHostWasm (host-wasm.ts): the
28
+ * code-size budget and the loader cache key cannot read a Module's size or
29
+ * identity from JS.
24
30
  */
25
31
  export interface WasmModule {
26
- wasm: ArrayBuffer;
32
+ wasm: ArrayBuffer | WebAssembly.Module;
27
33
  }
28
34
  /** Plain string = type inferred from file extension (.js or .py). */
29
35
  export type ModuleContent = string | JsModule | CjsModule | PyModule | TextModule | DataModule | JsonModule | WasmModule;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vendor/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,CAAA;CAAE;AAC1C,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAA;CAAE;AAC5C,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,CAAA;CAAE;AACjD,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,OAAO,CAAA;CAAE;AAC7C;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,CAAA;CAAE;AAEjD,qEAAqE;AACrE,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,UAAU;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,IAAI,cAAc,CAAC;IAChC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAC;CACvE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/C;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,GAAG,UAAU,CAAC;CAC/D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vendor/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,MAAM,CAAA;CAAE;AAC1C,MAAM,WAAW,QAAQ;IAAG,EAAE,EAAE,MAAM,CAAA;CAAE;AACxC,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAA;CAAE;AAC5C,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,CAAA;CAAE;AACjD,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,OAAO,CAAA;CAAE;AAC7C;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC,MAAM,CAAA;CAAE;AAEtE,qEAAqE;AACrE,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,WAAW,UAAU;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,IAAI,cAAc,CAAC;IAChC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAC;CACvE;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/C;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,GAAG,UAAU,CAAC;CAC/D"}
@@ -24,11 +24,7 @@ export interface NimbusCtxExports {
24
24
  key: string;
25
25
  name: string | null;
26
26
  depth: number;
27
- supervisor: {
28
- doId: string;
29
- pid: number;
30
- writerId: string;
31
- };
27
+ supervisor: ResidentSupervisorProps;
32
28
  stage?: unknown;
33
29
  };
34
30
  }) => LoadedWorkerEntrypointStub;
@@ -40,11 +36,7 @@ export declare function getNimbusCtxExports(): NimbusCtxExports;
40
36
  * request rather than leaving it resident: their module map is assembled in
41
37
  * that stateless entrypoint's own isolate, never in a session DO.
42
38
  */
43
- export declare function createLoadedWorkerEntrypoint(ctxExports: NimbusCtxExports, supervisor: {
44
- doId: string;
45
- pid: number;
46
- writerId: string;
47
- }, stage: unknown, name?: string | null): Promise<LoadedWorkerEntrypointStub>;
39
+ export declare function createLoadedWorkerEntrypoint(ctxExports: NimbusCtxExports, supervisor: ResidentSupervisorProps, stage: unknown, name?: string | null): Promise<LoadedWorkerEntrypointStub>;
48
40
  /** What an unkeyed `LOADER.load` hands back. */
49
41
  interface LoadedWorkerStub {
50
42
  getEntrypoint(): LoadedWorkerEntrypointStub;
@@ -133,13 +125,8 @@ export declare function cloneStorage(ctx: DurableObjectState, clone: {
133
125
  export declare function residentFacetName(slot: number): string;
134
126
  /** The prefix every durable application's facet name carries. */
135
127
  export declare const DURABLE_FACET_NAME_PREFIX = "app-slot-";
136
- /**
137
- * Drop one facet's SQLite by name — the ONLY call site that may delete facet
138
- * storage. `spawnResident` releases ephemeral processes with abort+delete
139
- * (storage is slot-reuse hygiene) and durable ones with abort alone (the
140
- * storage IS the durable application's state); explicit removal arrives here
141
- * through the coordinator's durable-slot book, owner-checked.
142
- */
128
+ /** The facet a running resident process `pid` lives in on this actor, for its storage ledger row. */
129
+ export declare function residentFacetOf(ctx: DurableObjectState, pid: number): string | undefined;
143
130
  export declare function deleteFacetStorage(ctx: DurableObjectState, name: string): void;
144
131
  /**
145
132
  * What `processes(ctx, env).spawn` hands back: a running process, minus its placement.
@@ -1 +1 @@
1
- {"version":3,"file":"workerd-facet-host.d.ts","sourceRoot":"","sources":["../src/workerd-facet-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workerd-facet-host.d.ts","sourceRoot":"","sources":["../src/workerd-facet-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAoBH,OAAO,EAGL,KAAK,aAAa,EAElB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AAK7B,+DAA+D;AAC/D,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5D,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAC/B,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE;QACjC,KAAK,EAAE;YACL,GAAG,EAAE,MAAM,CAAC;YACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;YACpB,KAAK,EAAE,MAAM,CAAC;YACd,UAAU,EAAE,uBAAuB,CAAC;YACpC,KAAK,CAAC,EAAE,OAAO,CAAC;SACjB,CAAC;KACH,KAAK,0BAA0B,CAAC;CAClC;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CAMtD;AAED;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,gBAAgB,EAC5B,UAAU,EAAE,uBAAuB,EACnC,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,MAAM,GAAG,IAAW,GACzB,OAAO,CAAC,0BAA0B,CAAC,CAerC;AA8BD,gDAAgD;AAChD,UAAU,gBAAgB;IACxB,aAAa,IAAI,0BAA0B,CAAC;CAC7C;AAED;;;;;;;;;;;;;GAaG;AACH,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,OAAO,GAAG;QAAE,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAC9F,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAaD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,kBAAkB,EACvB,KAAK,EAAE;IACL,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD,GACA,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,iEAAiE;AACjE,eAAO,MAAM,yBAAyB,cAAc,CAAC;AA4FrD,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExF;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9E;AAID;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9F;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAEnF;AAED,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBADH,GAAG,EAAE,kBAAkB,EACvB,GAAG,EAAE,gBAAgB;IAGxC,8EAA8E;IAC9E,KAAK,CACH,IAAI,EAAE,MAAM,kBAAkB,EAC9B,UAAU,EAAE,uBAAuB,EACnC,MAAM,EAAE,iBAAiB,GACxB,aAAa;IAIhB;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,CAAC,EACH,UAAU,EAAE,uBAAuB,EACnC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1C,OAAO,CAAC,CAAC,CAAC;CAGd;AAiPD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,MAAM,kBAAkB,EAC9B,UAAU,EAAE,uBAAuB,EACnC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAelC"}
@@ -13,9 +13,11 @@
13
13
  * `HostedProcess` and never imports this file.
14
14
  */
15
15
  import { disposeRpcResource } from '@nimbus-sh/platform/rpc-dispose.js';
16
+ import { StorageLedger, forgetFacetStorage } from '@nimbus-sh/core/runtime/storage-ledger.js';
16
17
  import { getCtxExports, stagedBootAssembler, supervisorEntrypoint, supervisorEntrypointName, } from './composition.js';
17
- import { assertModuleMapWithinCodeLimit, beginLoaderFetch, facetNameCount, facetNameCountDurable, recordFacetNameMinted, recordLoaderId, withDynamicWorkerCapNamed, withFacetBudgetNamed, } from './budgets.js';
18
+ import { assertModuleMapWithinCodeLimit, beginLoaderFetch, facetNameCount, facetNameCountDurable, recordFacetNameMinted, withDynamicWorkerCapNamed, withFacetBudgetNamed, } from './budgets.js';
18
19
  import { RESIDENT_PROCESS_CLASS, residentLoaderConfig, } from './process-fabric.js';
20
+ import { supervisorLoaderKey } from './supervisor-props.js';
19
21
  export function getNimbusCtxExports() {
20
22
  const ctxExports = getCtxExports();
21
23
  if (!ctxExports || typeof ctxExports !== 'object') {
@@ -35,7 +37,9 @@ export async function createLoadedWorkerEntrypoint(ctxExports, supervisor, stage
35
37
  }
36
38
  return await ctxExports.NimbusLoadedEntrypoint({
37
39
  props: {
38
- key: `nimbus-process:${supervisor.doId}:${supervisor.pid}`,
40
+ // The entrypoint's loader outlives this instance, and a warm worker keeps
41
+ // the SUPERVISOR binding it was built with.
42
+ key: supervisorLoaderKey(`nimbus-process:${supervisor.doId}:${supervisor.pid}`, supervisor),
39
43
  name,
40
44
  depth: 0,
41
45
  supervisor,
@@ -83,7 +87,7 @@ export async function cloneStorage(ctx, clone) {
83
87
  const facets = facetContainer(ctx);
84
88
  if (typeof facets.clone !== 'function') {
85
89
  throw new Error('Nimbus: ctx.facets.clone is unavailable in this runtime; the reflink image '
86
- + 'path needs deployed Cloudflare workerd (local workerd <= 1.20260603.1 lacks it)');
90
+ + 'path needs workerd 1.20260926.1 or later, or deployed Cloudflare workerd');
87
91
  }
88
92
  const { src, dst } = clone;
89
93
  if (!(await clone.populated(src))) {
@@ -126,37 +130,38 @@ export const DURABLE_FACET_NAME_PREFIX = 'app-slot-';
126
130
  * Slot books, per hosting actor, because the facet index is per Durable
127
131
  * Object.
128
132
  *
129
- * Keyed weakly off `ctx`, and that is sound rather than lossy: a facet cannot
130
- * outlive the Durable Object hosting it, so a book that goes away with its
131
- * host describes nothing that still exists. A fresh incarnation restarts at
132
- * slot 0 and re-attaches to the SQLite a previous incarnation left there —
133
- * which is safe for the reason the store is sealed until it has reconciled.
134
- * Its persisted cursor is either datable against the current authority, in
135
- * which case the ACQUIRE delta brings it current, or it carries a different
136
- * VFS epoch, in which case `invalidatedSince` can only answer poison and the
137
- * whole store is dropped. A process therefore cannot boot onto a previous
138
- * tenant's filesystem even when release never ran.
133
+ * Keyed weakly off `ctx`, so a book describes one incarnation. A facet that
134
+ * is still running when that incarnation ends outlives it (measured: a timer
135
+ * or an outgoing call keeps it going), and a `get` of its name with a new
136
+ * class then resets the whole object. So a fresh incarnation's first get of
137
+ * each name ends whatever runs there first: a minted `proc-slot-` name is
138
+ * deleted, which also wipes the storage a previous incarnation left, and an
139
+ * explicit name is aborted, which keeps it.
139
140
  *
140
- * The book names only the `proc-slot-` space. Durable `app-slot-` names are
141
- * allocated against DO storage instead (their owner survives a reset), so a
142
- * fresh incarnation's `next` starting at 0 can never collide with them even
141
+ * The book allocates only the `proc-slot-` space. Durable `app-slot-` names
142
+ * are allocated against DO storage instead (their owner survives a reset), so
143
+ * a fresh incarnation's `next` starting at 0 can never collide with them even
143
144
  * before the durable ledger is adopted.
144
145
  */
145
146
  const slotBooks = new WeakMap();
146
147
  function slotBook(ctx) {
147
148
  let book = slotBooks.get(ctx);
148
149
  if (!book) {
149
- book = { free: [], next: 0, held: new Map() };
150
+ book = { free: [], next: 0, held: new Map(), live: new Set() };
150
151
  slotBooks.set(ctx, book);
151
152
  }
152
153
  return book;
153
154
  }
154
- /** Take a slot for `pid`, reusing a returned one before minting a new name. */
155
+ /**
156
+ * Take a slot for `pid`, reusing a returned one before minting a new name.
157
+ * `minted` names may still hold storage a previous incarnation of this actor
158
+ * left there, so the caller deletes it before the first get.
159
+ */
155
160
  function acquireSlot(ctx, pid) {
156
161
  const book = slotBook(ctx);
157
162
  const existing = book.held.get(pid);
158
163
  if (existing !== undefined)
159
- return existing;
164
+ return { slot: existing, minted: false };
160
165
  const reused = book.free.length > 0;
161
166
  const slot = reused ? book.free.shift() : book.next++;
162
167
  book.held.set(pid, slot);
@@ -164,7 +169,7 @@ function acquireSlot(ctx, pid) {
164
169
  // in the budgets ledger (see budgets.ts).
165
170
  if (!reused)
166
171
  recordFacetNameMinted(ctx, book.next);
167
- return slot;
172
+ return { slot, minted: !reused };
168
173
  }
169
174
  /** Return `pid`'s slot to the free list. */
170
175
  function releaseSlot(ctx, pid) {
@@ -177,14 +182,34 @@ function releaseSlot(ctx, pid) {
177
182
  book.free.sort((a, b) => a - b);
178
183
  }
179
184
  /**
180
- * Drop one facet's SQLite by name — the ONLY call site that may delete facet
181
- * storage. `spawnResident` releases ephemeral processes with abort+delete
182
- * (storage is slot-reuse hygiene) and durable ones with abort alone (the
183
- * storage IS the durable application's state); explicit removal arrives here
184
- * through the coordinator's durable-slot book, owner-checked.
185
+ * Drop one facet's SQLite by name, and its row in the session's storage
186
+ * ledger (N18) in the same step: the only way a facet database is deleted.
187
+ * `spawnResident` releases ephemeral processes with abort+delete (storage is
188
+ * slot-reuse hygiene) and durable ones with abort alone (the storage IS the
189
+ * durable application's state); explicit removal arrives here through the
190
+ * coordinator's durable-slot book, owner-checked.
185
191
  */
192
+ /** The session's storage ledger (N18), over this actor's SQL; null where it has none. */
193
+ function sessionLedger(ctx) {
194
+ const sql = ctx.storage?.sql;
195
+ return sql ? new StorageLedger(sql) : null;
196
+ }
197
+ const facetNames = new WeakMap();
198
+ function facetOfPid(ctx) {
199
+ let names = facetNames.get(ctx);
200
+ if (!names)
201
+ facetNames.set(ctx, names = new Map());
202
+ return names;
203
+ }
204
+ /** The facet a running resident process `pid` lives in on this actor, for its storage ledger row. */
205
+ export function residentFacetOf(ctx, pid) {
206
+ return facetNames.get(ctx)?.get(pid);
207
+ }
186
208
  export function deleteFacetStorage(ctx, name) {
187
209
  facetContainer(ctx).delete(name);
210
+ const sql = ctx.storage?.sql;
211
+ if (sql)
212
+ forgetFacetStorage(sql, name);
188
213
  }
189
214
  /**
190
215
  * The process surface of one hosting actor: how a resident process comes
@@ -241,8 +266,15 @@ function spawnResident(ctx, env, disk, supervisor, params) {
241
266
  throw new Error(`Nimbus: an explicit facet name must carry the '${DURABLE_FACET_NAME_PREFIX}' `
242
267
  + `prefix, got '${explicit.name}'`);
243
268
  }
244
- const slot = explicit ? undefined : acquireSlot(ctx, params.pid);
269
+ const grant = explicit ? undefined : acquireSlot(ctx, params.pid);
270
+ const slot = grant?.slot;
245
271
  const name = explicit ? explicit.name : residentFacetName(slot);
272
+ if (grant?.minted) {
273
+ try {
274
+ deleteFacetStorage(ctx, name);
275
+ }
276
+ catch { /* nothing stored under this name */ }
277
+ }
246
278
  // The start callback is the ONLY way this facet is ever created, and it
247
279
  // fires AT MOST ONCE. Every later use goes through the stub below, so the
248
280
  // callback running a second time means the facet was released or died —
@@ -260,10 +292,23 @@ function spawnResident(ctx, env, disk, supervisor, params) {
260
292
  + 'it is not restarted');
261
293
  }
262
294
  evaluated = true;
263
- return { class: residentProcessClass(ctx, env, disk, supervisor, params) };
295
+ return { class: residentProcessClass(env, disk, supervisor, params, loaderKey) };
264
296
  };
297
+ const book = slotBook(ctx);
298
+ const ledger = sessionLedger(ctx);
299
+ // A warm worker keeps the SUPERVISOR binding it was built with, and the
300
+ // loader outlives this instance.
301
+ const loaderKey = supervisorLoaderKey(params.workerKey, supervisor);
265
302
  let facet;
266
303
  try {
304
+ // N18: the fill is admitted, and recorded under the facet's name, before
305
+ // the facet exists; a refusal leaves no facet.
306
+ if (ledger !== null && params.storageBytes !== undefined)
307
+ ledger.fill(name, params.storageBytes);
308
+ // get() with a new class on a facet an earlier incarnation left running resets this object.
309
+ if (explicit && !book.live.has(name)) {
310
+ facets.abort(name, new Error('Nimbus: a new incarnation takes this facet name'));
311
+ }
267
312
  facet = facets.get(name, start);
268
313
  }
269
314
  catch (error) {
@@ -271,16 +316,29 @@ function spawnResident(ctx, env, disk, supervisor, params) {
271
316
  releaseSlot(ctx, params.pid);
272
317
  throw withFacetBudgetNamed(facetNameCount(ctx), error);
273
318
  }
319
+ if (explicit)
320
+ book.live.add(name);
321
+ // The facet's worker is one Dynamic Worker in flight for as long as the
322
+ // process is resident, not only while a call is open: its WebSockets and
323
+ // streamed responses outlive the calls the ledger could bracket, and a
324
+ // request can reach it at any moment. Held from here to `release`, so no
325
+ // fan-out spends the slot a running process needs.
326
+ const endResidency = beginLoaderFetch(ctx, loaderKey);
327
+ facetOfPid(ctx).set(params.pid, name);
274
328
  let disposed = false;
275
329
  const release = async () => {
276
330
  if (disposed)
277
331
  return;
278
332
  disposed = true;
279
333
  released = true;
334
+ facetOfPid(ctx).delete(params.pid);
335
+ endResidency();
280
336
  try {
281
337
  facets.abort(name, new Error('Nimbus: resident process released'));
282
338
  }
283
339
  catch { /* already gone */ }
340
+ if (explicit)
341
+ book.live.delete(name);
284
342
  // The two release classes: an ephemeral facet's SQLite is slot-reuse
285
343
  // hygiene — the name is handed out again, so the store must not be — and
286
344
  // a durable one's is the application itself: abort ends the process, the
@@ -288,7 +346,7 @@ function spawnResident(ctx, env, disk, supervisor, params) {
288
346
  // deleteFacetStorage call ever drops it.
289
347
  if (!explicit?.durable) {
290
348
  try {
291
- facets.delete(name);
349
+ deleteFacetStorage(ctx, name);
292
350
  }
293
351
  catch { /* already gone */ }
294
352
  }
@@ -299,7 +357,11 @@ function spawnResident(ctx, env, disk, supervisor, params) {
299
357
  };
300
358
  let started;
301
359
  try {
302
- started = facet.startProcess(params.startArgs);
360
+ // The allowance the ledger admitted, for the facet's store to keep under.
361
+ const startArgs = ledger !== null && params.storageBytes !== undefined && params.startArgs !== null && typeof params.startArgs === 'object'
362
+ ? { ...params.startArgs, storage: { facet: name, grant: params.storageBytes } }
363
+ : params.startArgs;
364
+ started = facet.startProcess(startArgs);
303
365
  }
304
366
  catch (error) {
305
367
  void release();
@@ -309,7 +371,18 @@ function spawnResident(ctx, env, disk, supervisor, params) {
309
371
  // this one, and it is annotated AFTER awaiting the ledger — the first
310
372
  // failure of a fresh incarnation must compare against the persisted count,
311
373
  // not the zero its adoption read has not yet replaced.
312
- started = started.catch(async (error) => {
374
+ started = started.then((payload) => {
375
+ // Once the facet is up (N18) its row is the cap its store keeps under
376
+ // (what it measures plus what it may still grow into), or what it
377
+ // measures if that is more (overshoot).
378
+ const { databaseSize: size, storageCap: cap } = (payload ?? {});
379
+ const measured = typeof size === 'number' && Number.isFinite(size) ? size : null;
380
+ const capped = typeof cap === 'number' && Number.isFinite(cap) ? cap : null;
381
+ const row = capped !== null ? Math.max(capped, measured ?? 0) : measured;
382
+ if (ledger !== null && row !== null)
383
+ ledger.reportSize(name, row);
384
+ return payload;
385
+ }, async (error) => {
313
386
  throw withFacetBudgetNamed(await facetNameCountDurable(ctx), error);
314
387
  });
315
388
  // A caller reads whichever of `started` and the lifecycle it needs, so keep
@@ -333,22 +406,15 @@ function spawnResident(ctx, env, disk, supervisor, params) {
333
406
  * assembles its module map at most once and the bytes never stay resident in
334
407
  * the hosting DO's heap.
335
408
  */
336
- function residentProcessClass(ctx, env, disk, supervisor, params) {
409
+ function residentProcessClass(env, disk, supervisor, params, loaderKey) {
337
410
  const loader = env.LOADER;
338
411
  if (!loader || typeof loader.get !== 'function') {
339
412
  throw new Error('Nimbus: env.LOADER binding missing or invalid. Resident processes require '
340
413
  + 'the Worker Loader binding; add it via worker_loaders in wrangler.jsonc.');
341
414
  }
342
- try {
343
- const worker = loader
344
- .get(params.workerKey, () => residentWorkerConfig(env, disk, supervisor, params.boot))
345
- .getDurableObjectClass(RESIDENT_PROCESS_CLASS);
346
- recordLoaderId(ctx, params.workerKey);
347
- return worker;
348
- }
349
- catch (error) {
350
- throw withDynamicWorkerCapNamed(ctx, error);
351
- }
415
+ return loader
416
+ .get(loaderKey, () => residentWorkerConfig(env, disk, supervisor, params.boot))
417
+ .getDurableObjectClass(RESIDENT_PROCESS_CLASS);
352
418
  }
353
419
  async function runOneShot(ctx, env, supervisor, params, consume) {
354
420
  const loader = env.LOADER;
@@ -389,24 +455,24 @@ async function runOneShot(ctx, env, supervisor, params, consume) {
389
455
  throw new Error('Nimbus: one-shot runtime entrypoint has no fetch method');
390
456
  }
391
457
  params.onLoaded?.();
392
- // The unkeyed worker is a live dynamic worker for exactly this call, so
393
- // the run is a Loader fetch on the hosting actor's ledger — bracketed,
394
- // never wrapped: see beginLoaderFetch for the measured DO-poisoning
395
- // hazard, and the pipelined-`fetch.call` note above for its sibling.
396
- const endFetch = beginLoaderFetch(ctx);
397
- let response;
458
+ // The unkeyed worker is one distinct dynamic worker in flight until its
459
+ // response is consumed (the body streams from it), keyed by this run's
460
+ // writer id — bracketed, never wrapped: see beginLoaderFetch for the
461
+ // measured DO-poisoning hazard, and the pipelined-`fetch.call` note above
462
+ // for its sibling.
463
+ const endFetch = beginLoaderFetch(ctx, `one-shot:${params.writerId}`);
398
464
  try {
399
- response = await ep.fetch(params.request);
465
+ const response = await ep.fetch(params.request);
466
+ try {
467
+ return await consume(response);
468
+ }
469
+ finally {
470
+ disposeRpcResource(response);
471
+ }
400
472
  }
401
473
  finally {
402
474
  endFetch();
403
475
  }
404
- try {
405
- return await consume(response);
406
- }
407
- finally {
408
- disposeRpcResource(response);
409
- }
410
476
  }
411
477
  catch (error) {
412
478
  throw withDynamicWorkerCapNamed(ctx, error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbus-sh/fabric",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "description": "The Cloudflare half of Nimbus \u2014 Durable Object facet hosting, dynamic-worker loader pools, the resident-process fabric, and DO alarm/hibernation machinery.",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -45,17 +45,17 @@
45
45
  "LICENSE"
46
46
  ],
47
47
  "scripts": {
48
- "build": "tsc -p tsconfig.json --noCheck --noEmit false --declaration true --declarationMap true --outDir dist --rootDir src",
49
- "prepack": "bun run build",
48
+ "build": "node ../../scripts/clean-dist.mjs && tsc -p tsconfig.json --noCheck --noEmit false --declaration true --declarationMap true --outDir dist --rootDir src",
49
+ "prepublishOnly": "bun ../../scripts/dist-integrity.mjs --publish",
50
50
  "typecheck": "tsc --noEmit"
51
51
  },
52
52
  "dependencies": {
53
- "@nimbus-sh/core": "^0.12.0",
54
- "@nimbus-sh/platform": "^0.5.1",
53
+ "@nimbus-sh/core": "^0.14.0",
54
+ "@nimbus-sh/platform": "^0.7.0",
55
55
  "zod": "^4.4.3"
56
56
  },
57
57
  "devDependencies": {
58
- "@cloudflare/workers-types": "^4.20250327.0",
58
+ "@cloudflare/workers-types": "^5.20260928.1",
59
59
  "typescript": "^5.7.0"
60
60
  },
61
61
  "publishConfig": {
package/src/bindings.ts CHANGED
@@ -324,6 +324,8 @@ const NimbusLoadedEntrypointPropsSchema = z.object({
324
324
  pid: z.number().int().nonnegative(),
325
325
  writerId: z.string().uuid(),
326
326
  route: HostRouteSchema.optional(),
327
+ /** The host instance's delivery incarnation (ResidentSupervisorProps). */
328
+ hostIncarnation: z.string().uuid().optional(),
327
329
  }).optional(),
328
330
  /**
329
331
  * Staged-artifact spec, for a ONE-SHOT run. The module map — ~23 MB for