@nimbus-sh/platform 0.6.0 → 0.7.1

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.
@@ -66,7 +66,8 @@ export declare const DEFAULT_HOST_DISPATCH_METHOD = "supervisorOp";
66
66
  * Compose once per isolate. A second call with the same values is a no-op;
67
67
  * a second call with different values throws, naming both, so an embedder
68
68
  * whose composition lost to an earlier import learns it at startup rather
69
- * than from a facet that reached the wrong host.
69
+ * than from a facet that reached the wrong host. A host without
70
+ * `enhanced_error_serialization` is refused.
70
71
  */
71
72
  export declare function composeFabric(value: FabricComposition): void;
72
73
  export declare function adoptCtxExports(value: CtxExports): void;
@@ -1 +1 @@
1
- {"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,GAAG,OAAO,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAC7F,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC,CAAC;AAC/E,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEpF,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AACvD,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAI3D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAmB5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAEvD;AAED,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,qBAAoC,GAAG,yBAAyB,GAAG,IAAI,CAMrI;AAED,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAExD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,IAAI,SAAS,GAAG,IAAI,CAO5C;AAED,wBAAgB,mBAAmB,IAAI,mBAAmB,CASzD"}
1
+ {"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,IAAI,GAAG,OAAO,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAC7F,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,yBAAyB,GAAG,SAAS,CAAC,CAAC;AAC/E,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEpF,MAAM,WAAW,iBAAiB;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,sBAAsB,mBAAmB,CAAC;AACvD,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAmC3D;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAoB5D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAEvD;AAED,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAEjD;AAED,wBAAgB,oBAAoB,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,IAAI,qBAAoC,GAAG,yBAAyB,GAAG,IAAI,CAMrI;AAED,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAExD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,IAAI,SAAS,GAAG,IAAI,CAO5C;AAED,wBAAgB,mBAAmB,IAAI,mBAAmB,CASzD"}
@@ -2,13 +2,45 @@ export const DEFAULT_HOST_NAMESPACE = 'NIMBUS_SESSION';
2
2
  export const DEFAULT_HOST_DISPATCH_METHOD = 'supervisorOp';
3
3
  let composition = null;
4
4
  let ctxExports = null;
5
+ /**
6
+ * A program's filesystem errors reach it across workerd RPC, from the host
7
+ * that answers its supervisor binding, and the program branches on the POSIX
8
+ * `code` each one carries. workerd carries an error's own properties across
9
+ * RPC only when the sending AND the receiving isolate have
10
+ * `enhanced_error_serialization`, on by compatibility date from 2026-04-21:
11
+ * the serializer writes a native error as a host object with its own
12
+ * properties only under the flag (src/workerd/jsg/ser.c++,
13
+ * Serializer::IsHostObject), and the receiver reads that detail back only
14
+ * under it (src/workerd/jsg/util.c++, decodeTunneledException); see
15
+ * https://developers.cloudflare.com/workers/runtime-apis/rpc/error-handling/.
16
+ * Programs load at CF_COMPAT_DATE, past it. The host runs at its embedder's
17
+ * date, and below it every ENOENT would reach every program as a bare message
18
+ * it maps to EIO. So composing refuses such a host, wherever it composes
19
+ * (module scope: the Worker fails at startup; NimbusWorkspace.create: that
20
+ * call throws), and names both fixes: the flag alone keeps
21
+ * every other behavior of the embedder's date. Off workerd (bun, node) there
22
+ * is no RPC hop and no `Cloudflare` global to read.
23
+ */
24
+ function requireEnhancedErrorSerialization() {
25
+ // `typeof` of an undeclared global is 'undefined', not a ReferenceError.
26
+ if (typeof Cloudflare === 'undefined')
27
+ return;
28
+ if (Cloudflare.compatibilityFlags.enhanced_error_serialization === true)
29
+ return;
30
+ throw new Error('fabric: this Worker runs without the enhanced_error_serialization compatibility flag, so the '
31
+ + "code on a program's filesystem error (ENOENT, EEXIST, ...) would not survive the RPC back "
32
+ + 'to it. Add "enhanced_error_serialization" to compatibility_flags in your wrangler config, '
33
+ + 'or set compatibility_date to 2026-04-21 or later.');
34
+ }
5
35
  /**
6
36
  * Compose once per isolate. A second call with the same values is a no-op;
7
37
  * a second call with different values throws, naming both, so an embedder
8
38
  * whose composition lost to an earlier import learns it at startup rather
9
- * than from a facet that reached the wrong host.
39
+ * than from a facet that reached the wrong host. A host without
40
+ * `enhanced_error_serialization` is refused.
10
41
  */
11
42
  export function composeFabric(value) {
43
+ requireEnhancedErrorSerialization();
12
44
  if (!composition) {
13
45
  composition = value;
14
46
  return;
@@ -75,12 +75,6 @@ export interface DiagCounters {
75
75
  * Surfaced as `breakdown.prefetchCacheBytes`. A gauge, not a delta.
76
76
  */
77
77
  prefetchCacheBytes: number;
78
- /**
79
- * Bytes retained by the FacetManager's ESM→CJS transform cache, bounded by
80
- * ESM_TRANSFORM_CACHE_MAX_BYTES. Surfaced as `breakdown.transformCacheBytes`.
81
- * A gauge, not a delta.
82
- */
83
- transformCacheBytes: number;
84
78
  /** Install-facet counters. Populated by npm-installer after a
85
79
  * successful batch-facet dispatch returns. Confirms the install ran
86
80
  * in the facet (tarballsCompleted > 0) and surfaces the
@@ -119,6 +113,15 @@ export interface DiagCounters {
119
113
  * Empty when the most recent batch had zero errors. */
120
114
  errorsByModule: Record<string, string>;
121
115
  };
116
+ /**
117
+ * File contents and stdin the session has handed its processes, cumulative
118
+ * since isolate start: the bytes of each supervisor envelope's answer as it
119
+ * leaves the session (worker session/supervisor-op.ts answerSupervisorOp)
120
+ * from readFile, readFileBytes, fsRead, fsReadRange, fsReadBatch, the read
121
+ * an fsAcquired carries, and cpReadStdin (a pipe's read ahead). A run's
122
+ * delta is what it was handed, which bounds what it can hold.
123
+ */
124
+ supervisorAnsweredBytes: number;
122
125
  /** Pipelined R2 race outcomes. All counts are cumulative since
123
126
  * DO-isolate start. Per-tier cache statistics live in cache-stats. */
124
127
  r2: {
@@ -136,6 +139,8 @@ export interface DiagCounters {
136
139
  }
137
140
  /** Read a snapshot — caller-side mutations don't affect the singleton. */
138
141
  export declare function readDiagCounters(): DiagCounters;
142
+ /** Count `bytes` the session answered a process's supervisor call with. */
143
+ export declare function recordSupervisorAnswer(bytes: number): void;
139
144
  /** Set the install phase. */
140
145
  export declare function setInstallPhase(p: InstallPhase): void;
141
146
  /**
@@ -181,8 +186,6 @@ export declare function prefetchBundleEnd(bytes: number): void;
181
186
  * owns the number and reports it whenever it admits or evicts an entry.
182
187
  */
183
188
  export declare function setPrefetchCacheBytes(bytes: number): void;
184
- /** Publish the transform cache's live retained total; same contract as above. */
185
- export declare function setTransformCacheBytes(bytes: number): void;
186
189
  /** Fold facet-returned counters into the supervisor's diag state.
187
190
  * Called by npm-installer after the batch-facet returns; aggregates
188
191
  * rather than replaces so multiple install runs in the same DO
@@ -1 +1 @@
1
- {"version":3,"file":"diag-counters.d.ts","sourceRoot":"","sources":["../src/diag-counters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"diag-counters.d.ts","sourceRoot":"","sources":["../src/diag-counters.ts"],"names":[],"mappings":"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"}
@@ -23,7 +23,7 @@ const _counters = {
23
23
  inFlightRpcPayloadBytes: 0,
24
24
  prefetchBundleBytes: 0,
25
25
  prefetchCacheBytes: 0,
26
- transformCacheBytes: 0,
26
+ supervisorAnsweredBytes: 0,
27
27
  installFacet: {
28
28
  tarballsCompleted: 0,
29
29
  cumulativeBytesDecoded: 0,
@@ -48,6 +48,10 @@ const _counters = {
48
48
  export function readDiagCounters() {
49
49
  return { ..._counters };
50
50
  }
51
+ /** Count `bytes` the session answered a process's supervisor call with. */
52
+ export function recordSupervisorAnswer(bytes) {
53
+ _counters.supervisorAnsweredBytes += bytes;
54
+ }
51
55
  /** Set the install phase. */
52
56
  export function setInstallPhase(p) {
53
57
  _counters.installPhase = p;
@@ -123,11 +127,6 @@ export function setPrefetchCacheBytes(bytes) {
123
127
  const n = Number(bytes);
124
128
  _counters.prefetchCacheBytes = Number.isFinite(n) && n > 0 ? n : 0;
125
129
  }
126
- /** Publish the transform cache's live retained total; same contract as above. */
127
- export function setTransformCacheBytes(bytes) {
128
- const n = Number(bytes);
129
- _counters.transformCacheBytes = Number.isFinite(n) && n > 0 ? n : 0;
130
- }
131
130
  /** Fold facet-returned counters into the supervisor's diag state.
132
131
  * Called by npm-installer after the batch-facet returns; aggregates
133
132
  * rather than replaces so multiple install runs in the same DO
@@ -180,12 +180,6 @@ export interface HeapBreakdown {
180
180
  * the cache holds rather than a reservation it might use.
181
181
  */
182
182
  prefetchCacheBytes: number;
183
- /**
184
- * Bytes retained by the FacetManager's ESM→CJS transform cache
185
- * (diag-counters `transformCacheBytes`), the other cache that persists
186
- * across execs. Bounded by ESM_TRANSFORM_CACHE_MAX_BYTES.
187
- */
188
- transformCacheBytes: number;
189
183
  /**
190
184
  * Shared-budget occupancy not already represented by the named transient
191
185
  * counters. This covers full-budget owners and keeps cross-DO module-local
@@ -1 +1 @@
1
- {"version":3,"file":"heap-estimate.d.ts","sourceRoot":"","sources":["../src/heap-estimate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wBAAwB,CAAC;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,sFAM1B,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAO,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,SAAS,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IACrC;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,gBAAgB,EAAE,+BAA+B,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,uBAAuB,EAAE,MAAM,CAAC;IAChC,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;sEAEkE;IAClE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;OAYG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,4BAA4B,EAAE,MAAM,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAQnE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,YAAY,EACf,GAAG,EAAE,aAAa,GACjB,YAAY,CAoDd"}
1
+ {"version":3,"file":"heap-estimate.d.ts","sourceRoot":"","sources":["../src/heap-estimate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAEL,KAAK,+BAA+B,EACrC,MAAM,wBAAwB,CAAC;AAEhC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,sFAM1B,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAO,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,SAAS,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;IACrC;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,gBAAgB,EAAE,+BAA+B,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,uBAAuB,EAAE,MAAM,CAAC;IAChC,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,gBAAgB,EAAE,MAAM,CAAC;IACzB;;sEAEkE;IAClE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;OAYG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,4BAA4B,EAAE,MAAM,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAyBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAQnE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,YAAY,EACf,GAAG,EAAE,aAAa,GACjB,YAAY,CAkDd"}
@@ -160,7 +160,6 @@ export function estimateSupervisorHeap(c, vfs) {
160
160
  streamingBuffersBytes: c.inFlightRpcPayloadBytes,
161
161
  prefetchBundleBytes: c.prefetchBundleBytes,
162
162
  prefetchCacheBytes: c.prefetchCacheBytes,
163
- transformCacheBytes: c.transformCacheBytes,
164
163
  unattributedReservationBytes: Math.max(0, allocationBudget.current - transientAttributedBytes),
165
164
  };
166
165
  const estimatedBytes = breakdown.supervisorBaselineBytes +
@@ -170,7 +169,6 @@ export function estimateSupervisorHeap(c, vfs) {
170
169
  breakdown.streamingBuffersBytes +
171
170
  breakdown.prefetchBundleBytes +
172
171
  breakdown.prefetchCacheBytes +
173
- breakdown.transformCacheBytes +
174
172
  breakdown.unattributedReservationBytes;
175
173
  const percentOfCeiling = Math.round((estimatedBytes / SUPERVISOR_HEAP_CEILING_BYTES) * 1000) / 10;
176
174
  return {
@@ -13,8 +13,6 @@ export interface SupervisorAllocationBudgetStats {
13
13
  readonly current: number;
14
14
  readonly peak: number;
15
15
  readonly queued: number;
16
- /** Credit held for an owner's whole lifetime; see `acquireResident`. */
17
- readonly resident: number;
18
16
  }
19
17
  interface AllocationBudgetLifecycle {
20
18
  onActive?: () => void;
@@ -53,12 +51,6 @@ export declare class SupervisorAllocationBudget {
53
51
  * stops a large read overlapping a large write.
54
52
  */
55
53
  acquireWithoutLifecycle(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
56
- /**
57
- * Reserve bytes an owner holds for its whole lifetime, not for one
58
- * operation. Recorded as a floor: a later claim larger than what remains
59
- * around it is refused with both numbers rather than parked forever.
60
- */
61
- acquireResidentBytes(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
62
54
  private _acquire;
63
55
  }
64
56
  /**
@@ -91,11 +83,6 @@ export declare function acquireSupervisorAllocation(bytes: number, signal?: Abor
91
83
  * there to fill.
92
84
  */
93
85
  export declare function acquireSupervisorReadAllocation(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
94
- /**
95
- * Reserve bytes for the whole life of the owner that takes them — an image
96
- * a pool keeps until it is disposed. See `acquireResidentBytes`.
97
- */
98
- export declare function acquireResidentSupervisorAllocation(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
99
86
  /**
100
87
  * Reserve the full budget for an allocation whose retained size is not known
101
88
  * accurately enough to overlap safely with other heavy work.
@@ -1 +1 @@
1
- {"version":3,"file":"heavy-alloc-coord.d.ts","sourceRoot":"","sources":["../src/heavy-alloc-coord.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC/B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,UAAU,yBAAyB;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,0BAA0B;IAWnC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAX5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAK;gBAGlB,QAAQ,EAAE,MAAM,EACR,SAAS,GAAE,yBAA8B,EAC1D,OAAO,GAAE,yBAA8B;IAKzC,IAAI,KAAK,IAAI,+BAA+B,CAK3C;IAED;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI3E;;;;;;;;OAQG;IACH,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI3F;;;;OAIG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAI1E,QAAQ;CAsCvB;AAED;;;GAGG;AACH,UAAU,aAAa;IACrB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAWlE;AAqCD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAMjF;AAED,wBAAgB,8BAA8B,IAAI,+BAA+B,CAEhF"}
1
+ {"version":3,"file":"heavy-alloc-coord.d.ts","sourceRoot":"","sources":["../src/heavy-alloc-coord.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,EAC/B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,yBAAyB;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,0BAA0B;IAWnC,QAAQ,CAAC,QAAQ,EAAE,MAAM;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAX5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,MAAM,CAAS;IACvB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAK;gBAGlB,QAAQ,EAAE,MAAM,EACR,SAAS,GAAE,yBAA8B,EAC1D,OAAO,GAAE,yBAA8B;IAKzC,IAAI,KAAK,IAAI,+BAA+B,CAK3C;IAED;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI3E;;;;;;;;OAQG;IACH,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAI7E,QAAQ;CAmCvB;AAED;;;GAGG;AACH,UAAU,aAAa;IACrB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,IAAI,CAWlE;AAqCD;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAMjF;AAED,wBAAgB,8BAA8B,IAAI,+BAA+B,CAEhF"}
@@ -55,18 +55,8 @@ export class SupervisorAllocationBudget {
55
55
  acquireWithoutLifecycle(bytes, signal) {
56
56
  return this._acquire(bytes, signal, false);
57
57
  }
58
- /**
59
- * Reserve bytes an owner holds for its whole lifetime, not for one
60
- * operation. Recorded as a floor: a later claim larger than what remains
61
- * around it is refused with both numbers rather than parked forever.
62
- */
63
- acquireResidentBytes(bytes, signal) {
64
- return this._acquire(bytes, signal, true, true);
65
- }
66
- async _acquire(bytes, signal, drivesLifecycle, resident = false) {
67
- const credit = resident
68
- ? await this.credits.acquireResident(bytes, signal)
69
- : await this.credits.acquire(bytes, signal);
58
+ async _acquire(bytes, signal, drivesLifecycle) {
59
+ const credit = await this.credits.acquire(bytes, signal);
70
60
  if (drivesLifecycle) {
71
61
  this.lifecycleHolders++;
72
62
  if (!this.active) {
@@ -178,13 +168,6 @@ export function acquireSupervisorAllocation(bytes, signal) {
178
168
  export function acquireSupervisorReadAllocation(bytes, signal) {
179
169
  return supervisorAllocationBudget.acquireWithoutLifecycle(bytes, signal);
180
170
  }
181
- /**
182
- * Reserve bytes for the whole life of the owner that takes them — an image
183
- * a pool keeps until it is disposed. See `acquireResidentBytes`.
184
- */
185
- export function acquireResidentSupervisorAllocation(bytes, signal) {
186
- return supervisorAllocationBudget.acquireResidentBytes(bytes, signal);
187
- }
188
171
  /**
189
172
  * Reserve the full budget for an allocation whose retained size is not known
190
173
  * accurately enough to overlap safely with other heavy work.
package/dist/limits.d.ts CHANGED
@@ -94,7 +94,7 @@ export declare const RESIDENT_KEEPALIVE_MS = 5000;
94
94
  export declare const RESIDENT_KEEPALIVE_DETACHED_MS = 60000;
95
95
  /**
96
96
  * Bytes one hibernatable WebSocket attachment may serialize to. Verified in
97
- * workerd source at the pinned version (v1.20260603.1,
97
+ * workerd source at the pinned version (v1.20260926.1,
98
98
  * src/workerd/api/web-socket.h: `MAX_ATTACHMENT_SIZE = 1024 * 16`). The
99
99
  * bound is on the SERIALIZED bytes — workerd re-serializes on every
100
100
  * `serializeAttachment` call to check it — not on UTF-8 JSON text, so a
package/dist/limits.js CHANGED
@@ -108,7 +108,7 @@ export const RESIDENT_KEEPALIVE_DETACHED_MS = 60_000;
108
108
  // ── WebSocket attachment bound ──────────────────────────────────────────
109
109
  /**
110
110
  * Bytes one hibernatable WebSocket attachment may serialize to. Verified in
111
- * workerd source at the pinned version (v1.20260603.1,
111
+ * workerd source at the pinned version (v1.20260926.1,
112
112
  * src/workerd/api/web-socket.h: `MAX_ATTACHMENT_SIZE = 1024 * 16`). The
113
113
  * bound is on the SERIALIZED bytes — workerd re-serializes on every
114
114
  * `serializeAttachment` call to check it — not on UTF-8 JSON text, so a
@@ -1 +1 @@
1
- {"version":3,"file":"oom-classify.d.ts","sourceRoot":"","sources":["../src/oom-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,QAAA,MAAM,UAAU,kLAYN,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAItD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAkErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW;AACrB,8CAA8C;AAC5C,oBAAoB;AACtB,8CAA8C;GAC5C,iBAAiB;AACnB,uEAAuE;GACrE,eAAe;AACjB,wDAAwD;GACtD,gBAAgB;AAClB;kDACkD;GAChD,YAAY;AACd,kEAAkE;GAChE,WAAW,CAAC;AAEhB;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAK7D;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAsB1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
1
+ {"version":3,"file":"oom-classify.d.ts","sourceRoot":"","sources":["../src/oom-classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAEH,QAAA,MAAM,UAAU,kLAYN,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAEjD,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAItD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAmErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAO1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW;AACrB,8CAA8C;AAC5C,oBAAoB;AACtB,8CAA8C;GAC5C,iBAAiB;AACnB,uEAAuE;GACrE,eAAe;AACjB,wDAAwD;GACtD,gBAAgB;AAClB;kDACkD;GAChD,YAAY;AACd,kEAAkE;GAChE,WAAW,CAAC;AAEhB;2DAC2D;AAC3D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAK7D;AAmBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAsB1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
@@ -125,11 +125,12 @@ export function classifyMessage(msg) {
125
125
  // Subrequest cap (Cloudflare platform)
126
126
  if (m.includes('too many subrequests'))
127
127
  return 'subrequest_cap';
128
- // Worker Loader concurrency cap (Cloudflare platform): a Durable Object
129
- // admits ~5-6 concurrent dynamic workers, and loader-cache entries are
130
- // never released — every distinct loader.get(id) permanently consumes a
131
- // slot, so this cap recurs until the DO itself is replaced.
132
- if (m.includes('too many concurrent dynamic workers'))
128
+ // Dynamic Worker concurrency limit (Cloudflare platform): a Durable Object
129
+ // may have a fixed number of distinct Dynamic Workers with in-flight
130
+ // requests at once (fabric budgets.ts, DO_DYNAMIC_WORKER_LIMIT). Production
131
+ // words it "Dynamic worker concurrency limit exceeded: each request may
132
+ // have up to 10 concurrent dynamic worker invocations. …".
133
+ if (m.includes('dynamic worker concurrency limit exceeded'))
133
134
  return 'dynamic_worker_cap';
134
135
  // Memory exhaustion. workerd trace outcome `exceededMemory`; in-band it
135
136
  // arrives as a `broken.exceededMemory` actor break, a "…exceeded [its]
@@ -0,0 +1,65 @@
1
+ /**
2
+ * tracing.ts — Workers custom spans, for modules that cannot import
3
+ * `cloudflare:workers`, as best-effort telemetry that never changes an
4
+ * outcome.
5
+ *
6
+ * The span API is `tracing` from `cloudflare:workers`
7
+ * (https://developers.cloudflare.com/workers/observability/traces/custom-spans/):
8
+ * `enterSpan(name, callback)` runs the callback in a span that is the active
9
+ * parent of every span and platform call made inside it — automatic RPC
10
+ * spans included — and ends it when the callback returns or its promise
11
+ * settles. A span records nothing unless the invocation was head-sampled
12
+ * (`observability.traces.head_sampling_rate`).
13
+ *
14
+ * `setAttributes` and `recordException` shipped on 2026-09-25
15
+ * (https://developers.cloudflare.com/changelog/post/2026-09-25-custom-span-apis/);
16
+ * a runtime from before then has `isTraced` and `setAttribute` only. So the
17
+ * code being traced never touches the runtime's span. It gets a
18
+ * {@link SpanRecorder}, which records only while the span is traced, uses
19
+ * whichever methods the runtime has, and swallows anything a span method
20
+ * throws.
21
+ *
22
+ * Core and fabric stay importable outside workerd, so they reach the API
23
+ * through this leaf: the Worker's composition root hands it over once, at
24
+ * module scope, with {@link adoptTracing}, exactly as it does `ctx.exports`
25
+ * (./composition.ts). With nothing adopted — unit tests, an embedder that
26
+ * never adopts — {@link traced} runs its callback with {@link untraced}.
27
+ */
28
+ /** Attribute values a span holds; `undefined` entries are ignored. */
29
+ export type SpanAttributes = Record<string, string | number | boolean | undefined>;
30
+ /** The runtime's `Span`, as any Workers runtime with `tracing` may have it. */
31
+ export interface RuntimeSpan {
32
+ readonly isTraced: boolean;
33
+ setAttribute?(key: string, value?: string | number | boolean): unknown;
34
+ setAttributes?(attributes: SpanAttributes): unknown;
35
+ recordException?(exception: string | {
36
+ code?: string | number;
37
+ name?: string;
38
+ message?: string;
39
+ stack?: string;
40
+ }): void;
41
+ }
42
+ /** The part of `cloudflare:workers`'s `tracing` Nimbus uses. */
43
+ export interface Tracer {
44
+ enterSpan<T>(name: string, callback: (span: RuntimeSpan) => T): T;
45
+ }
46
+ /** What traced code records on its span. Never throws; records nothing unless the span is traced. */
47
+ export interface SpanRecorder {
48
+ set(attributes: SpanAttributes): void;
49
+ /**
50
+ * Record `error` as an exception event. `code`, when given, replaces the
51
+ * error's own; `context` is prefixed to its message.
52
+ */
53
+ exception(error: unknown, code?: string, context?: string): void;
54
+ }
55
+ /** The recorder of a span that is not traced, or of no span at all. */
56
+ export declare const untraced: SpanRecorder;
57
+ /** Hand this isolate's `tracing` over. The first adoption stands, like `adoptCtxExports`. */
58
+ export declare function adoptTracing(value: Tracer): void;
59
+ /**
60
+ * Run `fn` in a span named `name` carrying `attributes`, and record on it the
61
+ * exception `fn` throws or its promise rejects with. What `fn` returns or
62
+ * throws reaches the caller unchanged, whatever the span does.
63
+ */
64
+ export declare function traced<T>(name: string, attributes: SpanAttributes, fn: (span: SpanRecorder) => T): T;
65
+ //# sourceMappingURL=tracing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,sEAAsE;AACtE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAEnF,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IACvE,aAAa,CAAC,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC;IACpD,eAAe,CAAC,CACd,SAAS,EAAE,MAAM,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9F,IAAI,CAAC;CACT;AAED,gEAAgE;AAChE,MAAM,WAAW,MAAM;IACrB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,CAAC,GAAG,CAAC,CAAC;CACnE;AAED,qGAAqG;AACrG,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClE;AAED,uEAAuE;AACvE,eAAO,MAAM,QAAQ,EAAE,YAA0D,CAAC;AAIlF,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEhD;AAyCD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,CAAC,GAAG,CAAC,CAkBpG"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * tracing.ts — Workers custom spans, for modules that cannot import
3
+ * `cloudflare:workers`, as best-effort telemetry that never changes an
4
+ * outcome.
5
+ *
6
+ * The span API is `tracing` from `cloudflare:workers`
7
+ * (https://developers.cloudflare.com/workers/observability/traces/custom-spans/):
8
+ * `enterSpan(name, callback)` runs the callback in a span that is the active
9
+ * parent of every span and platform call made inside it — automatic RPC
10
+ * spans included — and ends it when the callback returns or its promise
11
+ * settles. A span records nothing unless the invocation was head-sampled
12
+ * (`observability.traces.head_sampling_rate`).
13
+ *
14
+ * `setAttributes` and `recordException` shipped on 2026-09-25
15
+ * (https://developers.cloudflare.com/changelog/post/2026-09-25-custom-span-apis/);
16
+ * a runtime from before then has `isTraced` and `setAttribute` only. So the
17
+ * code being traced never touches the runtime's span. It gets a
18
+ * {@link SpanRecorder}, which records only while the span is traced, uses
19
+ * whichever methods the runtime has, and swallows anything a span method
20
+ * throws.
21
+ *
22
+ * Core and fabric stay importable outside workerd, so they reach the API
23
+ * through this leaf: the Worker's composition root hands it over once, at
24
+ * module scope, with {@link adoptTracing}, exactly as it does `ctx.exports`
25
+ * (./composition.ts). With nothing adopted — unit tests, an embedder that
26
+ * never adopts — {@link traced} runs its callback with {@link untraced}.
27
+ */
28
+ /** The recorder of a span that is not traced, or of no span at all. */
29
+ export const untraced = Object.freeze({ set() { }, exception() { } });
30
+ let tracer = null;
31
+ /** Hand this isolate's `tracing` over. The first adoption stands, like `adoptCtxExports`. */
32
+ export function adoptTracing(value) {
33
+ tracer ??= value;
34
+ }
35
+ function recorderFor(span) {
36
+ try {
37
+ if (!span.isTraced)
38
+ return untraced;
39
+ }
40
+ catch {
41
+ return untraced;
42
+ }
43
+ return {
44
+ set(attributes) {
45
+ try {
46
+ if (typeof span.setAttributes === 'function') {
47
+ span.setAttributes(attributes);
48
+ }
49
+ else if (typeof span.setAttribute === 'function') {
50
+ for (const [key, value] of Object.entries(attributes)) {
51
+ if (value !== undefined)
52
+ span.setAttribute(key, value);
53
+ }
54
+ }
55
+ }
56
+ catch { /* telemetry is best-effort */ }
57
+ },
58
+ exception(error, code, context = '') {
59
+ try {
60
+ if (typeof span.recordException !== 'function')
61
+ return;
62
+ if (error instanceof Error) {
63
+ const own = 'code' in error ? error.code : undefined;
64
+ span.recordException({
65
+ code: code ?? (typeof own === 'string' || typeof own === 'number' ? own : undefined),
66
+ name: error.name,
67
+ message: context + error.message,
68
+ stack: error.stack,
69
+ });
70
+ }
71
+ else {
72
+ span.recordException(code === undefined && !context
73
+ ? String(error)
74
+ : { code, message: context + String(error) });
75
+ }
76
+ }
77
+ catch { /* telemetry is best-effort */ }
78
+ },
79
+ };
80
+ }
81
+ /**
82
+ * Run `fn` in a span named `name` carrying `attributes`, and record on it the
83
+ * exception `fn` throws or its promise rejects with. What `fn` returns or
84
+ * throws reaches the caller unchanged, whatever the span does.
85
+ */
86
+ export function traced(name, attributes, fn) {
87
+ if (!tracer)
88
+ return fn(untraced);
89
+ return tracer.enterSpan(name, (runtimeSpan) => {
90
+ const span = recorderFor(runtimeSpan);
91
+ span.set(attributes);
92
+ let result;
93
+ try {
94
+ result = fn(span);
95
+ }
96
+ catch (error) {
97
+ span.exception(error);
98
+ throw error;
99
+ }
100
+ if (!(result instanceof Promise))
101
+ return result;
102
+ return result.catch((error) => {
103
+ span.exception(error);
104
+ throw error;
105
+ });
106
+ });
107
+ }
@@ -9,11 +9,6 @@ export interface WeightedCreditPoolStats {
9
9
  readonly current: number;
10
10
  readonly peak: number;
11
11
  readonly queued: number;
12
- /**
13
- * Credit held by owners that keep it for their whole lifetime rather than
14
- * for one operation — the floor no waiter can ever expect to get back.
15
- */
16
- readonly resident: number;
17
12
  }
18
13
  export interface WeightedCreditPoolOptions {
19
14
  /**
@@ -61,14 +56,6 @@ export declare class WeightedCreditPool {
61
56
  private isSmall;
62
57
  tryAcquire(bytes: number): ResizableCreditLease | null;
63
58
  acquire(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
64
- /**
65
- * Take credit that will be held for the owner's whole lifetime rather than
66
- * for one operation — the esbuild pool's wasm image is the case.
67
- *
68
- * Recorded as a floor so a later claim that could never fit around it is
69
- * refused with both numbers instead of parking in the FIFO forever.
70
- */
71
- acquireResident(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease>;
72
59
  private validateRequest;
73
60
  }
74
61
  //# sourceMappingURL=weighted-credit-pool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"weighted-credit-pool.d.ts","sourceRoot":"","sources":["../src/weighted-credit-pool.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAmJD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,kBAAkB;IAKjB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAJrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAEtB,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B;IAoB9E,IAAI,KAAK,IAAI,uBAAuB,CAUnC;IAED,OAAO,CAAC,OAAO;IAIf,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI;IAOtD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiB3E;;;;;;OAMG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IASnF,OAAO,CAAC,eAAe;CAOxB"}
1
+ {"version":3,"file":"weighted-credit-pool.d.ts","sourceRoot":"","sources":["../src/weighted-credit-pool.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkHD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,kBAAkB;IAKjB,QAAQ,CAAC,QAAQ,EAAE,MAAM;IAJrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAEtB,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B;IAoB9E,IAAI,KAAK,IAAI,uBAAuB,CASnC;IAED,OAAO,CAAC,OAAO;IAIf,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI;IAOtD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiB3E,OAAO,CAAC,eAAe;CAOxB"}
@@ -3,52 +3,27 @@ class CreditLane {
3
3
  capacity;
4
4
  current = 0;
5
5
  peak = 0;
6
- resident = 0;
7
6
  waiters = [];
8
7
  constructor(capacity) {
9
8
  this.capacity = capacity;
10
9
  }
11
10
  get stats() {
12
- return {
13
- current: this.current, peak: this.peak, queued: this.waiters.length, resident: this.resident,
14
- };
11
+ return { current: this.current, peak: this.peak, queued: this.waiters.length };
15
12
  }
16
13
  tryAcquire(bytes) {
17
14
  if (this.waiters.length > 0 || this.current + bytes > this.capacity)
18
15
  return null;
19
- return this.grant(bytes, false);
16
+ return this.grant(bytes);
20
17
  }
21
- /**
22
- * The largest claim this lane can ever grant: capacity less what resident
23
- * owners hold for their whole lifetime. A claim above it cannot be
24
- * satisfied by waiting, because nothing it is waiting for will be
25
- * released.
26
- */
27
- get grantableCeiling() {
28
- return this.capacity - this.resident;
29
- }
30
- acquire(bytes, signal, resident = false) {
18
+ acquire(bytes, signal) {
31
19
  if (signal?.aborted)
32
20
  return Promise.reject(abortError(signal));
33
- // Refuse a claim no amount of waiting can satisfy, rather than parking it
34
- // in the FIFO forever. A parked claim is indistinguishable from a caller
35
- // that stopped: no error, no timeout, and — because the queue refuses
36
- // everyone behind it — no further progress anywhere in the isolate. That
37
- // is what a real-vite launch looked like for four rounds of debugging.
38
- if (bytes > this.grantableCeiling) {
39
- return Promise.reject(new RangeError(`weighted credit claim of ${bytes} bytes can never be granted: capacity is ${this.capacity} `
40
- + `and ${this.resident} bytes are held by resident owners, leaving ${this.grantableCeiling}`));
41
- }
42
- const immediate = resident ? null : this.tryAcquire(bytes);
21
+ const immediate = this.tryAcquire(bytes);
43
22
  if (immediate)
44
23
  return Promise.resolve(immediate);
45
- if (resident && this.waiters.length === 0 && this.current + bytes <= this.capacity) {
46
- return Promise.resolve(this.grant(bytes, true));
47
- }
48
24
  return new Promise((resolve, reject) => {
49
25
  const waiter = {
50
26
  bytes,
51
- resident,
52
27
  resolve,
53
28
  reject,
54
29
  signal,
@@ -73,10 +48,8 @@ class CreditLane {
73
48
  this.drain();
74
49
  });
75
50
  }
76
- grant(bytes, resident) {
51
+ grant(bytes) {
77
52
  this.current += bytes;
78
- if (resident)
79
- this.resident += bytes;
80
53
  this.peak = Math.max(this.peak, this.current);
81
54
  let leasedBytes = bytes;
82
55
  let released = false;
@@ -94,8 +67,6 @@ class CreditLane {
94
67
  throw new RangeError(`weighted credit lease can only shrink to a positive safe integer no larger than ${leasedBytes}: ${nextBytes}`);
95
68
  }
96
69
  this.current -= leasedBytes - nextBytes;
97
- if (resident)
98
- this.resident -= leasedBytes - nextBytes;
99
70
  leasedBytes = nextBytes;
100
71
  this.drain();
101
72
  },
@@ -104,8 +75,6 @@ class CreditLane {
104
75
  return;
105
76
  released = true;
106
77
  this.current -= leasedBytes;
107
- if (resident)
108
- this.resident -= leasedBytes;
109
78
  if (this.current < 0) {
110
79
  throw new Error('weighted credit accounting underflow');
111
80
  }
@@ -126,7 +95,7 @@ class CreditLane {
126
95
  return;
127
96
  this.waiters.shift();
128
97
  waiter.signal?.removeEventListener('abort', waiter.onAbort);
129
- waiter.resolve(this.grant(waiter.bytes, waiter.resident));
98
+ waiter.resolve(this.grant(waiter.bytes));
130
99
  }
131
100
  }
132
101
  }
@@ -185,7 +154,6 @@ export class WeightedCreditPool {
185
154
  current: general.current + small.current,
186
155
  peak: general.peak + small.peak,
187
156
  queued: general.queued + small.queued,
188
- resident: general.resident + small.resident,
189
157
  };
190
158
  }
191
159
  isSmall(bytes) {
@@ -216,22 +184,6 @@ export class WeightedCreditPool {
216
184
  }
217
185
  return this.general.acquire(bytes, signal);
218
186
  }
219
- /**
220
- * Take credit that will be held for the owner's whole lifetime rather than
221
- * for one operation — the esbuild pool's wasm image is the case.
222
- *
223
- * Recorded as a floor so a later claim that could never fit around it is
224
- * refused with both numbers instead of parking in the FIFO forever.
225
- */
226
- acquireResident(bytes, signal) {
227
- try {
228
- this.validateRequest(bytes);
229
- }
230
- catch (error) {
231
- return Promise.reject(error);
232
- }
233
- return this.general.acquire(bytes, signal, true);
234
- }
235
187
  validateRequest(bytes) {
236
188
  if (!Number.isSafeInteger(bytes) || bytes <= 0 || bytes > this.capacity) {
237
189
  throw new RangeError(`weighted credit request must be a positive safe integer no larger than ${this.capacity}: ${bytes}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbus-sh/platform",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "The measured Cloudflare platform truths Nimbus is built on \u2014 error taxonomy, limits tables, budget coordination, and wire-format primitives, with zero runtime dependencies.",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -48,7 +48,7 @@
48
48
  "typecheck": "tsc --noEmit"
49
49
  },
50
50
  "devDependencies": {
51
- "@cloudflare/workers-types": "^4.20250327.0",
51
+ "@cloudflare/workers-types": "^5.20260928.1",
52
52
  "typescript": "^5.7.0"
53
53
  },
54
54
  "publishConfig": {
@@ -66,13 +66,46 @@ export const DEFAULT_HOST_DISPATCH_METHOD = 'supervisorOp';
66
66
  let composition: FabricComposition | null = null;
67
67
  let ctxExports: CtxExports | null = null;
68
68
 
69
+ /**
70
+ * A program's filesystem errors reach it across workerd RPC, from the host
71
+ * that answers its supervisor binding, and the program branches on the POSIX
72
+ * `code` each one carries. workerd carries an error's own properties across
73
+ * RPC only when the sending AND the receiving isolate have
74
+ * `enhanced_error_serialization`, on by compatibility date from 2026-04-21:
75
+ * the serializer writes a native error as a host object with its own
76
+ * properties only under the flag (src/workerd/jsg/ser.c++,
77
+ * Serializer::IsHostObject), and the receiver reads that detail back only
78
+ * under it (src/workerd/jsg/util.c++, decodeTunneledException); see
79
+ * https://developers.cloudflare.com/workers/runtime-apis/rpc/error-handling/.
80
+ * Programs load at CF_COMPAT_DATE, past it. The host runs at its embedder's
81
+ * date, and below it every ENOENT would reach every program as a bare message
82
+ * it maps to EIO. So composing refuses such a host, wherever it composes
83
+ * (module scope: the Worker fails at startup; NimbusWorkspace.create: that
84
+ * call throws), and names both fixes: the flag alone keeps
85
+ * every other behavior of the embedder's date. Off workerd (bun, node) there
86
+ * is no RPC hop and no `Cloudflare` global to read.
87
+ */
88
+ function requireEnhancedErrorSerialization(): void {
89
+ // `typeof` of an undeclared global is 'undefined', not a ReferenceError.
90
+ if (typeof Cloudflare === 'undefined') return;
91
+ if (Cloudflare.compatibilityFlags.enhanced_error_serialization === true) return;
92
+ throw new Error(
93
+ 'fabric: this Worker runs without the enhanced_error_serialization compatibility flag, so the '
94
+ + "code on a program's filesystem error (ENOENT, EEXIST, ...) would not survive the RPC back "
95
+ + 'to it. Add "enhanced_error_serialization" to compatibility_flags in your wrangler config, '
96
+ + 'or set compatibility_date to 2026-04-21 or later.',
97
+ );
98
+ }
99
+
69
100
  /**
70
101
  * Compose once per isolate. A second call with the same values is a no-op;
71
102
  * a second call with different values throws, naming both, so an embedder
72
103
  * whose composition lost to an earlier import learns it at startup rather
73
- * than from a facet that reached the wrong host.
104
+ * than from a facet that reached the wrong host. A host without
105
+ * `enhanced_error_serialization` is refused.
74
106
  */
75
107
  export function composeFabric(value: FabricComposition): void {
108
+ requireEnhancedErrorSerialization();
76
109
  if (!composition) {
77
110
  composition = value;
78
111
  return;
@@ -82,12 +82,6 @@ export interface DiagCounters {
82
82
  * Surfaced as `breakdown.prefetchCacheBytes`. A gauge, not a delta.
83
83
  */
84
84
  prefetchCacheBytes: number;
85
- /**
86
- * Bytes retained by the FacetManager's ESM→CJS transform cache, bounded by
87
- * ESM_TRANSFORM_CACHE_MAX_BYTES. Surfaced as `breakdown.transformCacheBytes`.
88
- * A gauge, not a delta.
89
- */
90
- transformCacheBytes: number;
91
85
  /** Install-facet counters. Populated by npm-installer after a
92
86
  * successful batch-facet dispatch returns. Confirms the install ran
93
87
  * in the facet (tarballsCompleted > 0) and surfaces the
@@ -126,6 +120,15 @@ export interface DiagCounters {
126
120
  * Empty when the most recent batch had zero errors. */
127
121
  errorsByModule: Record<string, string>;
128
122
  };
123
+ /**
124
+ * File contents and stdin the session has handed its processes, cumulative
125
+ * since isolate start: the bytes of each supervisor envelope's answer as it
126
+ * leaves the session (worker session/supervisor-op.ts answerSupervisorOp)
127
+ * from readFile, readFileBytes, fsRead, fsReadRange, fsReadBatch, the read
128
+ * an fsAcquired carries, and cpReadStdin (a pipe's read ahead). A run's
129
+ * delta is what it was handed, which bounds what it can hold.
130
+ */
131
+ supervisorAnsweredBytes: number;
129
132
  /** Pipelined R2 race outcomes. All counts are cumulative since
130
133
  * DO-isolate start. Per-tier cache statistics live in cache-stats. */
131
134
  r2: {
@@ -147,7 +150,7 @@ const _counters: DiagCounters = {
147
150
  inFlightRpcPayloadBytes: 0,
148
151
  prefetchBundleBytes: 0,
149
152
  prefetchCacheBytes: 0,
150
- transformCacheBytes: 0,
153
+ supervisorAnsweredBytes: 0,
151
154
  installFacet: {
152
155
  tarballsCompleted: 0,
153
156
  cumulativeBytesDecoded: 0,
@@ -174,6 +177,11 @@ export function readDiagCounters(): DiagCounters {
174
177
  return { ..._counters };
175
178
  }
176
179
 
180
+ /** Count `bytes` the session answered a process's supervisor call with. */
181
+ export function recordSupervisorAnswer(bytes: number): void {
182
+ _counters.supervisorAnsweredBytes += bytes;
183
+ }
184
+
177
185
  /** Set the install phase. */
178
186
  export function setInstallPhase(p: InstallPhase): void {
179
187
  _counters.installPhase = p;
@@ -250,12 +258,6 @@ export function setPrefetchCacheBytes(bytes: number): void {
250
258
  _counters.prefetchCacheBytes = Number.isFinite(n) && n > 0 ? n : 0;
251
259
  }
252
260
 
253
- /** Publish the transform cache's live retained total; same contract as above. */
254
- export function setTransformCacheBytes(bytes: number): void {
255
- const n = Number(bytes);
256
- _counters.transformCacheBytes = Number.isFinite(n) && n > 0 ? n : 0;
257
- }
258
-
259
261
  /** Fold facet-returned counters into the supervisor's diag state.
260
262
  * Called by npm-installer after the batch-facet returns; aggregates
261
263
  * rather than replaces so multiple install runs in the same DO
@@ -200,12 +200,6 @@ export interface HeapBreakdown {
200
200
  * the cache holds rather than a reservation it might use.
201
201
  */
202
202
  prefetchCacheBytes: number;
203
- /**
204
- * Bytes retained by the FacetManager's ESM→CJS transform cache
205
- * (diag-counters `transformCacheBytes`), the other cache that persists
206
- * across execs. Bounded by ESM_TRANSFORM_CACHE_MAX_BYTES.
207
- */
208
- transformCacheBytes: number;
209
203
  /**
210
204
  * Shared-budget occupancy not already represented by the named transient
211
205
  * counters. This covers full-budget owners and keeps cross-DO module-local
@@ -303,7 +297,6 @@ export function estimateSupervisorHeap(
303
297
  streamingBuffersBytes: c.inFlightRpcPayloadBytes,
304
298
  prefetchBundleBytes: c.prefetchBundleBytes,
305
299
  prefetchCacheBytes: c.prefetchCacheBytes,
306
- transformCacheBytes: c.transformCacheBytes,
307
300
  unattributedReservationBytes: Math.max(
308
301
  0,
309
302
  allocationBudget.current - transientAttributedBytes,
@@ -318,7 +311,6 @@ export function estimateSupervisorHeap(
318
311
  breakdown.streamingBuffersBytes +
319
312
  breakdown.prefetchBundleBytes +
320
313
  breakdown.prefetchCacheBytes +
321
- breakdown.transformCacheBytes +
322
314
  breakdown.unattributedReservationBytes;
323
315
 
324
316
  const percentOfCeiling = Math.round(
@@ -24,8 +24,6 @@ export interface SupervisorAllocationBudgetStats {
24
24
  readonly current: number;
25
25
  readonly peak: number;
26
26
  readonly queued: number;
27
- /** Credit held for an owner's whole lifetime; see `acquireResident`. */
28
- readonly resident: number;
29
27
  }
30
28
 
31
29
  interface AllocationBudgetLifecycle {
@@ -84,24 +82,12 @@ export class SupervisorAllocationBudget {
84
82
  return this._acquire(bytes, signal, false);
85
83
  }
86
84
 
87
- /**
88
- * Reserve bytes an owner holds for its whole lifetime, not for one
89
- * operation. Recorded as a floor: a later claim larger than what remains
90
- * around it is refused with both numbers rather than parked forever.
91
- */
92
- acquireResidentBytes(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease> {
93
- return this._acquire(bytes, signal, true, true);
94
- }
95
-
96
85
  private async _acquire(
97
86
  bytes: number,
98
87
  signal: AbortSignal | undefined,
99
88
  drivesLifecycle: boolean,
100
- resident = false,
101
89
  ): Promise<ResizableCreditLease> {
102
- const credit = resident
103
- ? await this.credits.acquireResident(bytes, signal)
104
- : await this.credits.acquire(bytes, signal);
90
+ const credit = await this.credits.acquire(bytes, signal);
105
91
  if (drivesLifecycle) {
106
92
  this.lifecycleHolders++;
107
93
  if (!this.active) {
@@ -238,17 +224,6 @@ export function acquireSupervisorReadAllocation(
238
224
  return supervisorAllocationBudget.acquireWithoutLifecycle(bytes, signal);
239
225
  }
240
226
 
241
- /**
242
- * Reserve bytes for the whole life of the owner that takes them — an image
243
- * a pool keeps until it is disposed. See `acquireResidentBytes`.
244
- */
245
- export function acquireResidentSupervisorAllocation(
246
- bytes: number,
247
- signal?: AbortSignal,
248
- ): Promise<ResizableCreditLease> {
249
- return supervisorAllocationBudget.acquireResidentBytes(bytes, signal);
250
- }
251
-
252
227
  /**
253
228
  * Reserve the full budget for an allocation whose retained size is not known
254
229
  * accurately enough to overlap safely with other heavy work.
package/src/limits.ts CHANGED
@@ -125,7 +125,7 @@ export const RESIDENT_KEEPALIVE_DETACHED_MS = 60_000;
125
125
 
126
126
  /**
127
127
  * Bytes one hibernatable WebSocket attachment may serialize to. Verified in
128
- * workerd source at the pinned version (v1.20260603.1,
128
+ * workerd source at the pinned version (v1.20260926.1,
129
129
  * src/workerd/api/web-socket.h: `MAX_ATTACHMENT_SIZE = 1024 * 16`). The
130
130
  * bound is on the SERIALIZED bytes — workerd re-serializes on every
131
131
  * `serializeAttachment` call to check it — not on UTF-8 JSON text, so a
@@ -127,11 +127,12 @@ export function classifyMessage(msg: string): OomCause {
127
127
  // Subrequest cap (Cloudflare platform)
128
128
  if (m.includes('too many subrequests')) return 'subrequest_cap';
129
129
 
130
- // Worker Loader concurrency cap (Cloudflare platform): a Durable Object
131
- // admits ~5-6 concurrent dynamic workers, and loader-cache entries are
132
- // never released — every distinct loader.get(id) permanently consumes a
133
- // slot, so this cap recurs until the DO itself is replaced.
134
- if (m.includes('too many concurrent dynamic workers')) return 'dynamic_worker_cap';
130
+ // Dynamic Worker concurrency limit (Cloudflare platform): a Durable Object
131
+ // may have a fixed number of distinct Dynamic Workers with in-flight
132
+ // requests at once (fabric budgets.ts, DO_DYNAMIC_WORKER_LIMIT). Production
133
+ // words it "Dynamic worker concurrency limit exceeded: each request may
134
+ // have up to 10 concurrent dynamic worker invocations. …".
135
+ if (m.includes('dynamic worker concurrency limit exceeded')) return 'dynamic_worker_cap';
135
136
 
136
137
  // Memory exhaustion. workerd trace outcome `exceededMemory`; in-band it
137
138
  // arrives as a `broken.exceededMemory` actor break, a "…exceeded [its]
package/src/tracing.ts ADDED
@@ -0,0 +1,129 @@
1
+ /**
2
+ * tracing.ts — Workers custom spans, for modules that cannot import
3
+ * `cloudflare:workers`, as best-effort telemetry that never changes an
4
+ * outcome.
5
+ *
6
+ * The span API is `tracing` from `cloudflare:workers`
7
+ * (https://developers.cloudflare.com/workers/observability/traces/custom-spans/):
8
+ * `enterSpan(name, callback)` runs the callback in a span that is the active
9
+ * parent of every span and platform call made inside it — automatic RPC
10
+ * spans included — and ends it when the callback returns or its promise
11
+ * settles. A span records nothing unless the invocation was head-sampled
12
+ * (`observability.traces.head_sampling_rate`).
13
+ *
14
+ * `setAttributes` and `recordException` shipped on 2026-09-25
15
+ * (https://developers.cloudflare.com/changelog/post/2026-09-25-custom-span-apis/);
16
+ * a runtime from before then has `isTraced` and `setAttribute` only. So the
17
+ * code being traced never touches the runtime's span. It gets a
18
+ * {@link SpanRecorder}, which records only while the span is traced, uses
19
+ * whichever methods the runtime has, and swallows anything a span method
20
+ * throws.
21
+ *
22
+ * Core and fabric stay importable outside workerd, so they reach the API
23
+ * through this leaf: the Worker's composition root hands it over once, at
24
+ * module scope, with {@link adoptTracing}, exactly as it does `ctx.exports`
25
+ * (./composition.ts). With nothing adopted — unit tests, an embedder that
26
+ * never adopts — {@link traced} runs its callback with {@link untraced}.
27
+ */
28
+
29
+ /** Attribute values a span holds; `undefined` entries are ignored. */
30
+ export type SpanAttributes = Record<string, string | number | boolean | undefined>;
31
+
32
+ /** The runtime's `Span`, as any Workers runtime with `tracing` may have it. */
33
+ export interface RuntimeSpan {
34
+ readonly isTraced: boolean;
35
+ setAttribute?(key: string, value?: string | number | boolean): unknown;
36
+ setAttributes?(attributes: SpanAttributes): unknown;
37
+ recordException?(
38
+ exception: string | { code?: string | number; name?: string; message?: string; stack?: string },
39
+ ): void;
40
+ }
41
+
42
+ /** The part of `cloudflare:workers`'s `tracing` Nimbus uses. */
43
+ export interface Tracer {
44
+ enterSpan<T>(name: string, callback: (span: RuntimeSpan) => T): T;
45
+ }
46
+
47
+ /** What traced code records on its span. Never throws; records nothing unless the span is traced. */
48
+ export interface SpanRecorder {
49
+ set(attributes: SpanAttributes): void;
50
+ /**
51
+ * Record `error` as an exception event. `code`, when given, replaces the
52
+ * error's own; `context` is prefixed to its message.
53
+ */
54
+ exception(error: unknown, code?: string, context?: string): void;
55
+ }
56
+
57
+ /** The recorder of a span that is not traced, or of no span at all. */
58
+ export const untraced: SpanRecorder = Object.freeze({ set() {}, exception() {} });
59
+
60
+ let tracer: Tracer | null = null;
61
+
62
+ /** Hand this isolate's `tracing` over. The first adoption stands, like `adoptCtxExports`. */
63
+ export function adoptTracing(value: Tracer): void {
64
+ tracer ??= value;
65
+ }
66
+
67
+ function recorderFor(span: RuntimeSpan): SpanRecorder {
68
+ try {
69
+ if (!span.isTraced) return untraced;
70
+ } catch {
71
+ return untraced;
72
+ }
73
+ return {
74
+ set(attributes) {
75
+ try {
76
+ if (typeof span.setAttributes === 'function') {
77
+ span.setAttributes(attributes);
78
+ } else if (typeof span.setAttribute === 'function') {
79
+ for (const [key, value] of Object.entries(attributes)) {
80
+ if (value !== undefined) span.setAttribute(key, value);
81
+ }
82
+ }
83
+ } catch { /* telemetry is best-effort */ }
84
+ },
85
+ exception(error, code, context = '') {
86
+ try {
87
+ if (typeof span.recordException !== 'function') return;
88
+ if (error instanceof Error) {
89
+ const own = 'code' in error ? error.code : undefined;
90
+ span.recordException({
91
+ code: code ?? (typeof own === 'string' || typeof own === 'number' ? own : undefined),
92
+ name: error.name,
93
+ message: context + error.message,
94
+ stack: error.stack,
95
+ });
96
+ } else {
97
+ span.recordException(code === undefined && !context
98
+ ? String(error)
99
+ : { code, message: context + String(error) });
100
+ }
101
+ } catch { /* telemetry is best-effort */ }
102
+ },
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Run `fn` in a span named `name` carrying `attributes`, and record on it the
108
+ * exception `fn` throws or its promise rejects with. What `fn` returns or
109
+ * throws reaches the caller unchanged, whatever the span does.
110
+ */
111
+ export function traced<T>(name: string, attributes: SpanAttributes, fn: (span: SpanRecorder) => T): T {
112
+ if (!tracer) return fn(untraced);
113
+ return tracer.enterSpan(name, (runtimeSpan) => {
114
+ const span = recorderFor(runtimeSpan);
115
+ span.set(attributes);
116
+ let result: T;
117
+ try {
118
+ result = fn(span);
119
+ } catch (error) {
120
+ span.exception(error);
121
+ throw error;
122
+ }
123
+ if (!(result instanceof Promise)) return result;
124
+ return result.catch((error: unknown) => {
125
+ span.exception(error);
126
+ throw error;
127
+ }) as T;
128
+ });
129
+ }
@@ -11,11 +11,6 @@ export interface WeightedCreditPoolStats {
11
11
  readonly current: number;
12
12
  readonly peak: number;
13
13
  readonly queued: number;
14
- /**
15
- * Credit held by owners that keep it for their whole lifetime rather than
16
- * for one operation — the floor no waiter can ever expect to get back.
17
- */
18
- readonly resident: number;
19
14
  }
20
15
 
21
16
  export interface WeightedCreditPoolOptions {
@@ -34,8 +29,6 @@ export interface WeightedCreditPoolOptions {
34
29
 
35
30
  interface CreditWaiter {
36
31
  readonly bytes: number;
37
- /** Whether the granted lease counts toward the resident floor. */
38
- readonly resident: boolean;
39
32
  readonly resolve: (lease: ResizableCreditLease) => void;
40
33
  readonly reject: (error: Error) => void;
41
34
  readonly signal?: AbortSignal;
@@ -46,55 +39,27 @@ interface CreditWaiter {
46
39
  class CreditLane {
47
40
  private current = 0;
48
41
  private peak = 0;
49
- private resident = 0;
50
42
  private readonly waiters: CreditWaiter[] = [];
51
43
 
52
44
  constructor(readonly capacity: number) {}
53
45
 
54
46
  get stats(): WeightedCreditPoolStats {
55
- return {
56
- current: this.current, peak: this.peak, queued: this.waiters.length, resident: this.resident,
57
- };
47
+ return { current: this.current, peak: this.peak, queued: this.waiters.length };
58
48
  }
59
49
 
60
50
  tryAcquire(bytes: number): ResizableCreditLease | null {
61
51
  if (this.waiters.length > 0 || this.current + bytes > this.capacity) return null;
62
- return this.grant(bytes, false);
63
- }
64
-
65
- /**
66
- * The largest claim this lane can ever grant: capacity less what resident
67
- * owners hold for their whole lifetime. A claim above it cannot be
68
- * satisfied by waiting, because nothing it is waiting for will be
69
- * released.
70
- */
71
- get grantableCeiling(): number {
72
- return this.capacity - this.resident;
52
+ return this.grant(bytes);
73
53
  }
74
54
 
75
- acquire(bytes: number, signal?: AbortSignal, resident = false): Promise<ResizableCreditLease> {
55
+ acquire(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease> {
76
56
  if (signal?.aborted) return Promise.reject(abortError(signal));
77
- // Refuse a claim no amount of waiting can satisfy, rather than parking it
78
- // in the FIFO forever. A parked claim is indistinguishable from a caller
79
- // that stopped: no error, no timeout, and — because the queue refuses
80
- // everyone behind it — no further progress anywhere in the isolate. That
81
- // is what a real-vite launch looked like for four rounds of debugging.
82
- if (bytes > this.grantableCeiling) {
83
- return Promise.reject(new RangeError(
84
- `weighted credit claim of ${bytes} bytes can never be granted: capacity is ${this.capacity} `
85
- + `and ${this.resident} bytes are held by resident owners, leaving ${this.grantableCeiling}`,
86
- ));
87
- }
88
- const immediate = resident ? null : this.tryAcquire(bytes);
57
+ const immediate = this.tryAcquire(bytes);
89
58
  if (immediate) return Promise.resolve(immediate);
90
- if (resident && this.waiters.length === 0 && this.current + bytes <= this.capacity) {
91
- return Promise.resolve(this.grant(bytes, true));
92
- }
93
59
 
94
60
  return new Promise<ResizableCreditLease>((resolve, reject) => {
95
61
  const waiter: CreditWaiter = {
96
62
  bytes,
97
- resident,
98
63
  resolve,
99
64
  reject,
100
65
  signal,
@@ -119,9 +84,8 @@ class CreditLane {
119
84
  });
120
85
  }
121
86
 
122
- private grant(bytes: number, resident: boolean): ResizableCreditLease {
87
+ private grant(bytes: number): ResizableCreditLease {
123
88
  this.current += bytes;
124
- if (resident) this.resident += bytes;
125
89
  this.peak = Math.max(this.peak, this.current);
126
90
  let leasedBytes = bytes;
127
91
  let released = false;
@@ -143,7 +107,6 @@ class CreditLane {
143
107
  );
144
108
  }
145
109
  this.current -= leasedBytes - nextBytes;
146
- if (resident) this.resident -= leasedBytes - nextBytes;
147
110
  leasedBytes = nextBytes;
148
111
  this.drain();
149
112
  },
@@ -151,7 +114,6 @@ class CreditLane {
151
114
  if (released) return;
152
115
  released = true;
153
116
  this.current -= leasedBytes;
154
- if (resident) this.resident -= leasedBytes;
155
117
  if (this.current < 0) {
156
118
  throw new Error('weighted credit accounting underflow');
157
119
  }
@@ -172,7 +134,7 @@ class CreditLane {
172
134
  if (this.current + waiter.bytes > this.capacity) return;
173
135
  this.waiters.shift();
174
136
  waiter.signal?.removeEventListener('abort', waiter.onAbort!);
175
- waiter.resolve(this.grant(waiter.bytes, waiter.resident));
137
+ waiter.resolve(this.grant(waiter.bytes));
176
138
  }
177
139
  }
178
140
  }
@@ -233,7 +195,6 @@ export class WeightedCreditPool {
233
195
  current: general.current + small.current,
234
196
  peak: general.peak + small.peak,
235
197
  queued: general.queued + small.queued,
236
- resident: general.resident + small.resident,
237
198
  };
238
199
  }
239
200
 
@@ -265,22 +226,6 @@ export class WeightedCreditPool {
265
226
  return this.general.acquire(bytes, signal);
266
227
  }
267
228
 
268
- /**
269
- * Take credit that will be held for the owner's whole lifetime rather than
270
- * for one operation — the esbuild pool's wasm image is the case.
271
- *
272
- * Recorded as a floor so a later claim that could never fit around it is
273
- * refused with both numbers instead of parking in the FIFO forever.
274
- */
275
- acquireResident(bytes: number, signal?: AbortSignal): Promise<ResizableCreditLease> {
276
- try {
277
- this.validateRequest(bytes);
278
- } catch (error) {
279
- return Promise.reject(error as Error);
280
- }
281
- return this.general.acquire(bytes, signal, true);
282
- }
283
-
284
229
  private validateRequest(bytes: number): void {
285
230
  if (!Number.isSafeInteger(bytes) || bytes <= 0 || bytes > this.capacity) {
286
231
  throw new RangeError(