@elaraai/east 1.0.76 → 1.0.77

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 (32) hide show
  1. package/dist/src/serialization/beast2/index.d.ts +21 -0
  2. package/dist/src/serialization/beast2/index.d.ts.map +1 -1
  3. package/dist/src/serialization/beast2/index.js +55 -0
  4. package/dist/src/serialization/beast2/index.js.map +1 -1
  5. package/dist/src/serialization/beast2/v5/deflate.d.ts.map +1 -1
  6. package/dist/src/serialization/beast2/v5/deflate.js +147 -50
  7. package/dist/src/serialization/beast2/v5/deflate.js.map +1 -1
  8. package/dist/src/serialization/beast2/v5/deflate.spec.d.ts +6 -0
  9. package/dist/src/serialization/beast2/v5/deflate.spec.d.ts.map +1 -0
  10. package/dist/src/serialization/beast2/v5/deflate.spec.js +237 -0
  11. package/dist/src/serialization/beast2/v5/deflate.spec.js.map +1 -0
  12. package/dist/src/serialization/beast2/v5/frame-pool.d.ts +119 -0
  13. package/dist/src/serialization/beast2/v5/frame-pool.d.ts.map +1 -0
  14. package/dist/src/serialization/beast2/v5/frame-pool.js +235 -0
  15. package/dist/src/serialization/beast2/v5/frame-pool.js.map +1 -0
  16. package/dist/src/serialization/beast2/v5/frame-pool.spec.d.ts +6 -0
  17. package/dist/src/serialization/beast2/v5/frame-pool.spec.d.ts.map +1 -0
  18. package/dist/src/serialization/beast2/v5/frame-pool.spec.js +287 -0
  19. package/dist/src/serialization/beast2/v5/frame-pool.spec.js.map +1 -0
  20. package/dist/src/serialization/beast2/v5/frame-worker.d.ts +6 -0
  21. package/dist/src/serialization/beast2/v5/frame-worker.d.ts.map +1 -0
  22. package/dist/src/serialization/beast2/v5/frame-worker.js +40 -0
  23. package/dist/src/serialization/beast2/v5/frame-worker.js.map +1 -0
  24. package/dist/src/serialization/beast2/v5/stream.d.ts +63 -2
  25. package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -1
  26. package/dist/src/serialization/beast2/v5/stream.js +132 -9
  27. package/dist/src/serialization/beast2/v5/stream.js.map +1 -1
  28. package/dist/src/serialization/index.d.ts +1 -1
  29. package/dist/src/serialization/index.d.ts.map +1 -1
  30. package/dist/src/serialization/index.js +1 -1
  31. package/dist/src/serialization/index.js.map +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ /**
6
+ * The deterministic DEFLATE encoder, held to the bit-at-a-time original.
7
+ *
8
+ * e3 content-addresses beast2 bytes, so this encoder's output is part of the
9
+ * wire format: a byte that moves re-keys every stored collection. The
10
+ * word-packed rewrite (#762) changed only how bits reach the buffer, so the
11
+ * gate is a differential one — {@link referenceDeflateRaw} below is the
12
+ * pre-#762 implementation, kept verbatim as the oracle, and every input here
13
+ * must compress to exactly the same bytes under both. The inflate check on top
14
+ * proves the shared answer is really RFC 1951.
15
+ */
16
+ import { describe, test } from "node:test";
17
+ import assert from "node:assert/strict";
18
+ import { deterministicDeflateRaw } from "./deflate.js";
19
+ import { inflateRawPure } from "./inflate.js";
20
+ // ===================================================================
21
+ // The oracle: the encoder exactly as it stood before #762.
22
+ // ===================================================================
23
+ const WINDOW = 32768;
24
+ const MIN_MATCH = 3;
25
+ const MAX_MATCH = 258;
26
+ const HASH_SIZE = 1 << 15;
27
+ const HASH_MASK = HASH_SIZE - 1;
28
+ const MAX_CHAIN = 32;
29
+ const LEN_BASE = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];
30
+ const LEN_EXTRA = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];
31
+ const DIST_BASE = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];
32
+ const DIST_EXTRA = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];
33
+ /** The pre-#762 bit sink: one bit at a time, a byte at a time out. */
34
+ class ReferenceBitWriter {
35
+ buf;
36
+ len = 0;
37
+ cur = 0;
38
+ bit = 0;
39
+ constructor(capacity) {
40
+ this.buf = new Uint8Array(Math.max(64, capacity));
41
+ }
42
+ push(byte) {
43
+ if (this.len === this.buf.length) {
44
+ const grown = new Uint8Array(this.buf.length * 2);
45
+ grown.set(this.buf);
46
+ this.buf = grown;
47
+ }
48
+ this.buf[this.len++] = byte;
49
+ }
50
+ writeBits(value, count) {
51
+ for (let i = 0; i < count; i++) {
52
+ this.cur |= ((value >> i) & 1) << this.bit;
53
+ if (++this.bit === 8) {
54
+ this.push(this.cur);
55
+ this.cur = 0;
56
+ this.bit = 0;
57
+ }
58
+ }
59
+ }
60
+ writeCode(code, bits) {
61
+ for (let i = bits - 1; i >= 0; i--)
62
+ this.writeBits((code >> i) & 1, 1);
63
+ }
64
+ finish() {
65
+ if (this.bit > 0)
66
+ this.push(this.cur);
67
+ return this.buf.subarray(0, this.len);
68
+ }
69
+ }
70
+ function referenceWriteLitLen(bw, sym) {
71
+ if (sym <= 143)
72
+ bw.writeCode(0x30 + sym, 8);
73
+ else if (sym <= 255)
74
+ bw.writeCode(0x190 + sym - 144, 9);
75
+ else if (sym <= 279)
76
+ bw.writeCode(sym - 256, 7);
77
+ else
78
+ bw.writeCode(0xC0 + sym - 280, 8);
79
+ }
80
+ /** The encoder as it stood before #762 — the byte-identity oracle. */
81
+ function referenceDeflateRaw(src) {
82
+ const bw = new ReferenceBitWriter(Math.max(64, src.length >> 1));
83
+ bw.writeBits(1, 1);
84
+ bw.writeBits(1, 2);
85
+ const head = new Int32Array(HASH_SIZE).fill(-1);
86
+ const prev = new Int32Array(src.length > 0 ? src.length : 1).fill(-1);
87
+ const n = src.length;
88
+ const hashAt = (i) => ((src[i] << 10) ^ (src[i + 1] << 5) ^ src[i + 2]) & HASH_MASK;
89
+ const insert = (i) => {
90
+ if (i + MIN_MATCH > n)
91
+ return;
92
+ const h = hashAt(i);
93
+ prev[i] = head[h];
94
+ head[h] = i;
95
+ };
96
+ let pos = 0;
97
+ while (pos < n) {
98
+ let bestLen = 0;
99
+ let bestDist = 0;
100
+ if (pos + MIN_MATCH <= n) {
101
+ let cand = head[hashAt(pos)];
102
+ let chain = 0;
103
+ const maxLen = Math.min(MAX_MATCH, n - pos);
104
+ while (cand >= 0 && chain++ < MAX_CHAIN) {
105
+ const dist = pos - cand;
106
+ if (dist > WINDOW)
107
+ break;
108
+ let len = 0;
109
+ while (len < maxLen && src[cand + len] === src[pos + len])
110
+ len++;
111
+ if (len > bestLen) {
112
+ bestLen = len;
113
+ bestDist = dist;
114
+ if (len === maxLen)
115
+ break;
116
+ }
117
+ cand = prev[cand];
118
+ }
119
+ }
120
+ if (bestLen >= MIN_MATCH) {
121
+ let lc = 0;
122
+ while (lc < 28 && LEN_BASE[lc + 1] <= bestLen)
123
+ lc++;
124
+ referenceWriteLitLen(bw, 257 + lc);
125
+ bw.writeBits(bestLen - LEN_BASE[lc], LEN_EXTRA[lc]);
126
+ let dc = 0;
127
+ while (dc < 29 && DIST_BASE[dc + 1] <= bestDist)
128
+ dc++;
129
+ bw.writeCode(dc, 5);
130
+ bw.writeBits(bestDist - DIST_BASE[dc], DIST_EXTRA[dc]);
131
+ for (let i = 0; i < bestLen; i++)
132
+ insert(pos + i);
133
+ pos += bestLen;
134
+ }
135
+ else {
136
+ referenceWriteLitLen(bw, src[pos]);
137
+ insert(pos);
138
+ pos++;
139
+ }
140
+ }
141
+ referenceWriteLitLen(bw, 256);
142
+ return bw.finish();
143
+ }
144
+ // ===================================================================
145
+ // Inputs
146
+ // ===================================================================
147
+ /** xorshift32 — a fixed stream, so a failure reproduces exactly. */
148
+ function rng(seed) {
149
+ let s = seed >>> 0 || 1;
150
+ return () => {
151
+ s ^= s << 13;
152
+ s >>>= 0;
153
+ s ^= s >>> 17;
154
+ s ^= s << 5;
155
+ s >>>= 0;
156
+ return s;
157
+ };
158
+ }
159
+ function randomBytes(n, seed) {
160
+ const next = rng(seed);
161
+ const out = new Uint8Array(n);
162
+ for (let i = 0; i < n; i++)
163
+ out[i] = next() & 0xff;
164
+ return out;
165
+ }
166
+ /** Rows of a plausible table: repeated field names, drifting numbers. */
167
+ function structuredBytes(rows, seed) {
168
+ const next = rng(seed);
169
+ const parts = [];
170
+ for (let i = 0; i < rows; i++) {
171
+ parts.push(`{"id":${i},"site":"site-${i % 40}","region":"R${i % 7}",` +
172
+ `"f1":${(next() % 100000) / 1000},"n1":${i % 1000},"flag":${(next() & 1) === 1}}`);
173
+ }
174
+ return new TextEncoder().encode(parts.join("\n"));
175
+ }
176
+ function cases() {
177
+ const out = [];
178
+ // Degenerate lengths around the 3-byte minimum match and the word compare.
179
+ for (const n of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 31, 32, 33]) {
180
+ out.push({ name: `random ${n}B`, bytes: randomBytes(n, 0x5eed + n) });
181
+ out.push({ name: `one byte x${n}`, bytes: new Uint8Array(n).fill(0x41) });
182
+ }
183
+ // A run of one byte: the longest possible matches, back to back.
184
+ out.push({ name: "one byte x100k", bytes: new Uint8Array(100_000).fill(0) });
185
+ // Every byte distinct, then every byte distinct twice: no match, then a
186
+ // match at exactly the window's far edge.
187
+ const distinct = new Uint8Array(256);
188
+ for (let i = 0; i < 256; i++)
189
+ distinct[i] = i;
190
+ out.push({ name: "all distinct bytes", bytes: distinct });
191
+ const twice = new Uint8Array(512);
192
+ twice.set(distinct, 0);
193
+ twice.set(distinct, 256);
194
+ out.push({ name: "all distinct bytes, twice", bytes: twice });
195
+ // A block repeated at exactly WINDOW distance, and just past it.
196
+ for (const gap of [WINDOW - 1, WINDOW, WINDOW + 1]) {
197
+ const bytes = randomBytes(gap + 64, 0xc0ffee);
198
+ bytes.set(bytes.subarray(0, 64), gap);
199
+ out.push({ name: `64B repeated at ${gap}`, bytes });
200
+ }
201
+ // Incompressible and compressible bulk.
202
+ out.push({ name: "random 1 MiB", bytes: randomBytes(1 << 20, 0xabcdef) });
203
+ out.push({ name: "structured 4 MiB", bytes: structuredBytes(60_000, 0x1234) });
204
+ return out;
205
+ }
206
+ // ===================================================================
207
+ describe("beast2 v5 deterministic deflate", () => {
208
+ test("is byte-identical to the pre-#762 encoder", () => {
209
+ for (const { name, bytes } of cases()) {
210
+ const actual = deterministicDeflateRaw(bytes);
211
+ const expected = referenceDeflateRaw(bytes);
212
+ assert.deepEqual(Array.from(actual), Array.from(expected), `${name}: the word-packed encoder must reproduce the original's bytes`);
213
+ }
214
+ });
215
+ test("round-trips through inflate", () => {
216
+ for (const { name, bytes } of cases()) {
217
+ const round = inflateRawPure(deterministicDeflateRaw(bytes), bytes.length);
218
+ assert.deepEqual(Array.from(round), Array.from(bytes), `${name}: inflate(deflate(x)) === x`);
219
+ }
220
+ });
221
+ test("compresses a byte run hard, and never expands a frame beyond its literals", () => {
222
+ const run = new Uint8Array(100_000).fill(0x7f);
223
+ assert.ok(deterministicDeflateRaw(run).length < run.length / 100);
224
+ // Incompressible input still goes out as fixed-Huffman literals, which cost
225
+ // at most 9 bits each. The frame writer is what falls back to codec `none`.
226
+ const noise = randomBytes(64 * 1024, 0x99);
227
+ assert.ok(deterministicDeflateRaw(noise).length <= Math.ceil((noise.length * 9) / 8) + 16);
228
+ });
229
+ test("respects a subarray's bounds", () => {
230
+ // The word compare loads through a DataView, which must be built on the
231
+ // view's own window rather than the whole backing buffer.
232
+ const backing = randomBytes(4096, 0x777);
233
+ const middle = backing.subarray(1000, 3000);
234
+ assert.deepEqual(Array.from(deterministicDeflateRaw(middle)), Array.from(referenceDeflateRaw(middle)));
235
+ });
236
+ });
237
+ //# sourceMappingURL=deflate.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deflate.spec.js","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/deflate.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ /**
6
+ * Beast2 v5 frame pool — deflating frames on worker threads (issue #763).
7
+ *
8
+ * v5 frames are independent (one segment per frame, each decoded standalone),
9
+ * so a writer can deflate them in parallel with no format change, provided it
10
+ * puts them on the wire in submission order. The pool is only the parallel
11
+ * half: {@link Beast2Writer} submits each segment's logical bytes and appends
12
+ * the resulting frames in order, assigning index offsets as they land.
13
+ *
14
+ * The writer's API is synchronous — {@link Beast2Writer.write} is called from
15
+ * inside compiled East bodies (the emit sink) — so results cannot come back as
16
+ * messages the main thread would have to yield to receive. Each job instead
17
+ * carries three `SharedArrayBuffer`s: the logical bytes in, the frame bytes
18
+ * out, and a status cell the worker flips and `Atomics.notify`s. The main
19
+ * thread polls the cell to append what is done and `Atomics.wait`s on it only
20
+ * when it must (back-pressure, a settle, `finish`).
21
+ *
22
+ * Node-only and optional: without `worker_threads`, `SharedArrayBuffer` or a
23
+ * second CPU, {@link framePool} returns `null` and the writer frames inline,
24
+ * which yields the same bytes. Node's modules are reached through
25
+ * `process.getBuiltinModule` — as `frames.ts` reaches zlib — so browser
26
+ * bundles never see a `node:` import.
27
+ *
28
+ * A worker can die without flipping a status cell — a worker-thread OOM ends
29
+ * its isolate before its `catch` runs — and the main thread cannot receive the
30
+ * worker's `exit` event while it is blocked waiting on that worker's frame. So
31
+ * every wait is bounded: a frame pending past the wait timeout fails, the pool
32
+ * is abandoned, and the process frames inline from then on.
33
+ *
34
+ * The pool is process-wide and outlives the write that started it, so a
35
+ * long-lived process — an API server, a terminal UI — would otherwise keep one
36
+ * idle V8 isolate per CPU for good. A pool with no frame outstanding and no
37
+ * activity for the idle limit terminates its workers, and the next pooled
38
+ * write starts a new pool. A writer abandoned mid-flight never takes its
39
+ * frames, so it keeps the pool alive; the idle check is `unref`'d, so process
40
+ * exit is unaffected either way.
41
+ */
42
+ import type { Beast2Codec } from "./frames.js";
43
+ /** An upper bound on a frame's header: varint(codec) + varint(uncompressed
44
+ * length) + varint(payload length). A frame's payload never exceeds its
45
+ * logical bytes (`writeFrame` stores codec `none` when deflate does not
46
+ * shrink), so logical + this bounds a frame not yet written. */
47
+ export declare const FRAME_HEADER_MAX = 21;
48
+ /** A frame being deflated on a worker. */
49
+ export interface PendingFrame {
50
+ /** The logical bytes the frame carries — its payload's upper bound. */
51
+ readonly logicalLength: number;
52
+ /** Whether the frame is ready, without blocking. */
53
+ ready(): boolean;
54
+ /**
55
+ * The frame's wire bytes, blocking until the worker has written them.
56
+ *
57
+ * @returns the frame bytes
58
+ * @throws {Error} When the worker failed to build the frame, or stopped
59
+ * responding — the frame was still pending when the wait timed out, or its
60
+ * pool had already lost a worker. A lost worker abandons the pool: the
61
+ * process frames inline from then on.
62
+ */
63
+ take(): Uint8Array;
64
+ }
65
+ /** A process-wide set of frame workers. */
66
+ export interface FramePool {
67
+ /** Worker count — the writer queues at most two frames per worker. */
68
+ readonly workers: number;
69
+ /**
70
+ * Hands a segment's logical bytes to a worker.
71
+ *
72
+ * @param logical - the segment's logical bytes (copied; the caller may reuse them)
73
+ * @param codec - the requested frame codec
74
+ * @returns the frame, pending
75
+ */
76
+ submit(logical: Uint8Array, codec: Beast2Codec): PendingFrame;
77
+ /**
78
+ * Terminates every worker thread. A frame still pending on one never
79
+ * completes, so its {@link PendingFrame.take} fails once the wait times out.
80
+ *
81
+ * @returns a promise that settles once every thread has exited
82
+ * @internal
83
+ */
84
+ terminateWorkers(): Promise<void>;
85
+ }
86
+ /** The frame pool's tunable timeouts — see {@link configureFramePool}. */
87
+ export interface FramePoolSettings {
88
+ /** How long {@link PendingFrame.take} waits for one frame before it presumes
89
+ * the worker's thread lost, in milliseconds. */
90
+ waitTimeoutMs?: number;
91
+ /** How long a pool with no frame outstanding keeps its workers before it
92
+ * terminates them, in milliseconds. */
93
+ idleMs?: number;
94
+ }
95
+ /**
96
+ * The process's frame pool, created on first use — and again after an idle
97
+ * pool retired its workers.
98
+ *
99
+ * @returns the pool, or `null` when frames must be written inline — no Node
100
+ * `worker_threads`, no `SharedArrayBuffer`, a single CPU, not the main thread
101
+ * (a pool per worker would only oversubscribe), worker start-up failed, or
102
+ * an earlier pool lost a worker
103
+ */
104
+ export declare function framePool(): FramePool | null;
105
+ /**
106
+ * Changes the frame pool's timeouts, for tests that cannot wait them out.
107
+ *
108
+ * @param options - the settings to change; an omitted one keeps its value
109
+ * @returns every setting as it was before, to restore afterwards
110
+ * @internal
111
+ */
112
+ export declare function configureFramePool(options: FramePoolSettings): Required<FramePoolSettings>;
113
+ /** Status cell values, for the worker. @internal */
114
+ export declare const FRAME_STATUS: {
115
+ readonly PENDING: 0;
116
+ readonly DONE: 1;
117
+ readonly FAILED: 2;
118
+ };
119
+ //# sourceMappingURL=frame-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-pool.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/frame-pool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;iEAGiE;AACjE,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAOnC,0CAA0C;AAC1C,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oDAAoD;IACpD,KAAK,IAAI,OAAO,CAAC;IACjB;;;;;;;;OAQG;IACH,IAAI,IAAI,UAAU,CAAC;CACpB;AAED,2CAA2C;AAC3C,MAAM,WAAW,SAAS;IACxB,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,CAAC;IAC9D;;;;;;OAMG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAChC;qDACiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;4CACwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAuDD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,SAAS,GAAG,IAAI,CAM5C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAM1F;AA2JD,oDAAoD;AACpD,eAAO,MAAM,YAAY;;;;CAAqC,CAAC"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ /** An upper bound on a frame's header: varint(codec) + varint(uncompressed
6
+ * length) + varint(payload length). A frame's payload never exceeds its
7
+ * logical bytes (`writeFrame` stores codec `none` when deflate does not
8
+ * shrink), so logical + this bounds a frame not yet written. */
9
+ export const FRAME_HEADER_MAX = 21;
10
+ /** Status cell values. */
11
+ const PENDING = 0;
12
+ const DONE = 1;
13
+ const FAILED = 2;
14
+ /** How long pool creation waits for every worker to report it loaded. A
15
+ * worker boots in tens of milliseconds; this only bounds a broken install. */
16
+ const STARTUP_TIMEOUT_MS = 10_000;
17
+ /** The most workers the pool starts. A writer keeps two frames per worker in
18
+ * flight, so memory scales with the worker count, while deflate throughput
19
+ * flattens well before this (#763 measured 254 MB/s at 32 threads). east-c's
20
+ * writer caps its threads the same (`B2V5_POOL_MAX_THREADS`). */
21
+ const FRAME_POOL_MAX_WORKERS = 32;
22
+ /** How long {@link PendingFrame.take} waits for one frame before it presumes
23
+ * the worker's thread lost. A 4 MiB segment deflates in well under a second,
24
+ * so this fires only when the worker is gone. */
25
+ const FRAME_WAIT_TIMEOUT_MS = 60_000;
26
+ /** The slices a blocked {@link PendingFrame.take} waits in, checking its
27
+ * deadline between them. */
28
+ const FRAME_WAIT_SLICE_MS = 1_000;
29
+ /** How long a pool with no frame outstanding keeps its workers. Starting a
30
+ * pool costs tens of milliseconds, so a busy process never pays it twice;
31
+ * an idle one does not hold an isolate per CPU for its whole life. */
32
+ const FRAME_POOL_IDLE_MS = 30_000;
33
+ /** How often the live pool is checked for idleness (more often only when the
34
+ * idle limit is shorter). */
35
+ const IDLE_CHECK_INTERVAL_MS = 10_000;
36
+ /** The timeouts in force; {@link configureFramePool} changes them. */
37
+ const settings = {
38
+ waitTimeoutMs: FRAME_WAIT_TIMEOUT_MS,
39
+ idleMs: FRAME_POOL_IDLE_MS,
40
+ };
41
+ /** `undefined` until first asked for, and again once an idle pool retires;
42
+ * `null` when this runtime cannot pool, or once a pool has lost a worker. */
43
+ let shared;
44
+ /** The live pool's idle check; `undefined` while no pool is live. */
45
+ let idleCheck;
46
+ /**
47
+ * The process's frame pool, created on first use — and again after an idle
48
+ * pool retired its workers.
49
+ *
50
+ * @returns the pool, or `null` when frames must be written inline — no Node
51
+ * `worker_threads`, no `SharedArrayBuffer`, a single CPU, not the main thread
52
+ * (a pool per worker would only oversubscribe), worker start-up failed, or
53
+ * an earlier pool lost a worker
54
+ */
55
+ export function framePool() {
56
+ if (shared === undefined) {
57
+ shared = createPool();
58
+ armIdleCheck();
59
+ }
60
+ return shared;
61
+ }
62
+ /**
63
+ * Changes the frame pool's timeouts, for tests that cannot wait them out.
64
+ *
65
+ * @param options - the settings to change; an omitted one keeps its value
66
+ * @returns every setting as it was before, to restore afterwards
67
+ * @internal
68
+ */
69
+ export function configureFramePool(options) {
70
+ const previous = { ...settings };
71
+ if (options.waitTimeoutMs !== undefined)
72
+ settings.waitTimeoutMs = options.waitTimeoutMs;
73
+ if (options.idleMs !== undefined)
74
+ settings.idleMs = options.idleMs;
75
+ armIdleCheck();
76
+ return previous;
77
+ }
78
+ /**
79
+ * Gives up on a pool that lost a worker: terminates its threads and makes the
80
+ * process frame inline from then on — the same bytes, on the calling thread.
81
+ * Every frame still pending on the pool fails at once rather than waiting out
82
+ * its own timeout.
83
+ */
84
+ function abandonPool(pool) {
85
+ pool.lost = true;
86
+ void pool.terminateWorkers();
87
+ shared = null;
88
+ armIdleCheck();
89
+ }
90
+ /** Starts, restarts or stops the idle check so it runs exactly while a pool
91
+ * is live, at a period no longer than the idle limit. */
92
+ function armIdleCheck() {
93
+ if (idleCheck !== undefined)
94
+ clearInterval(idleCheck);
95
+ idleCheck = undefined;
96
+ if (!(shared instanceof WorkerFramePool))
97
+ return;
98
+ idleCheck = setInterval(retireIfIdle, Math.max(1, Math.min(IDLE_CHECK_INTERVAL_MS, settings.idleMs)));
99
+ // Never keeps a finished process alive.
100
+ idleCheck.unref?.();
101
+ }
102
+ /** Terminates the live pool's workers once no frame is outstanding and none
103
+ * has moved for the idle limit; the next {@link framePool} starts a new one. */
104
+ function retireIfIdle() {
105
+ const pool = shared;
106
+ if (pool instanceof WorkerFramePool && pool.outstanding === 0 && Date.now() - pool.lastActivity > settings.idleMs) {
107
+ void pool.terminateWorkers();
108
+ shared = undefined;
109
+ }
110
+ if (!(shared instanceof WorkerFramePool))
111
+ armIdleCheck();
112
+ }
113
+ /** The worker-thread pool {@link framePool} hands out. */
114
+ class WorkerFramePool {
115
+ workers;
116
+ /** Set once a worker stopped responding; every pending frame then fails. */
117
+ lost = false;
118
+ /** Frames submitted and not yet taken — a pool with any is never idle. */
119
+ outstanding = 0;
120
+ /** When a frame was last submitted or taken, or the pool started. */
121
+ lastActivity = Date.now();
122
+ threads;
123
+ next = 0;
124
+ constructor(threads) {
125
+ this.threads = threads;
126
+ this.workers = threads.length;
127
+ }
128
+ submit(logical, codec) {
129
+ const input = new SharedArrayBuffer(Math.max(1, logical.length));
130
+ new Uint8Array(input).set(logical);
131
+ const output = new SharedArrayBuffer(logical.length + FRAME_HEADER_MAX);
132
+ const status = new Int32Array(new SharedArrayBuffer(8));
133
+ this.threads[this.next].postMessage({ input, length: logical.length, output, status: status.buffer, codec });
134
+ this.next = (this.next + 1) % this.threads.length;
135
+ this.outstanding++;
136
+ this.lastActivity = Date.now();
137
+ let taken = false;
138
+ return {
139
+ logicalLength: logical.length,
140
+ ready: () => Atomics.load(status, 0) !== PENDING,
141
+ take: () => {
142
+ try {
143
+ const deadline = Date.now() + settings.waitTimeoutMs;
144
+ while (Atomics.load(status, 0) === PENDING) {
145
+ const remaining = deadline - Date.now();
146
+ if (this.lost || remaining <= 0) {
147
+ abandonPool(this);
148
+ throw new Error("beast2 v5: a frame worker stopped responding — its thread was lost");
149
+ }
150
+ Atomics.wait(status, 0, PENDING, Math.min(FRAME_WAIT_SLICE_MS, remaining));
151
+ }
152
+ if (Atomics.load(status, 0) === FAILED) {
153
+ throw new Error("beast2 v5: a frame worker failed to build a frame");
154
+ }
155
+ return new Uint8Array(output, 0, Atomics.load(status, 1)).slice();
156
+ }
157
+ finally {
158
+ // Taken once, however it ended: a failed frame is not outstanding.
159
+ if (!taken) {
160
+ taken = true;
161
+ this.outstanding--;
162
+ }
163
+ this.lastActivity = Date.now();
164
+ }
165
+ },
166
+ };
167
+ }
168
+ async terminateWorkers() {
169
+ await Promise.all(this.threads.map((worker) => worker.terminate()));
170
+ }
171
+ }
172
+ function createPool() {
173
+ if (typeof SharedArrayBuffer === "undefined" || typeof Atomics === "undefined")
174
+ return null;
175
+ const getBuiltin = globalThis
176
+ .process?.getBuiltinModule;
177
+ if (typeof getBuiltin !== "function")
178
+ return null;
179
+ const threads = getBuiltin("node:worker_threads");
180
+ const os = getBuiltin("node:os");
181
+ const fs = getBuiltin("node:fs");
182
+ if (!threads || !os || !fs || !threads.isMainThread)
183
+ return null;
184
+ const cpus = Math.min(FRAME_POOL_MAX_WORKERS, os.availableParallelism?.() ?? os.cpus().length);
185
+ if (cpus < 2)
186
+ return null;
187
+ // Bundled into a single file (or loaded as CommonJS), this module has no
188
+ // worker script beside it — frame inline rather than fail.
189
+ let script;
190
+ try {
191
+ script = new URL("./frame-worker.js", import.meta.url);
192
+ if (!fs.existsSync(script))
193
+ return null;
194
+ }
195
+ catch {
196
+ return null;
197
+ }
198
+ // Each worker reports it has LOADED through a shared cell before the pool
199
+ // is handed out. A worker that fails to load reports only through an
200
+ // `error` event — which the main thread cannot receive while it is blocked
201
+ // in `Atomics.wait` on that worker's first job. So a pool is only ever
202
+ // returned once every worker has proven it runs.
203
+ const ready = new Int32Array(new SharedArrayBuffer(4 * cpus));
204
+ const workers = [];
205
+ const abandon = () => {
206
+ for (const worker of workers)
207
+ void worker.terminate();
208
+ return null;
209
+ };
210
+ try {
211
+ for (let i = 0; i < cpus; i++) {
212
+ const worker = new threads.Worker(script, { workerData: { ready: ready.buffer, index: i } });
213
+ // Idle workers must not keep a finished process alive; a writer that
214
+ // is waiting on one is blocked on the main thread anyway.
215
+ worker.unref();
216
+ workers.push(worker);
217
+ }
218
+ }
219
+ catch {
220
+ return abandon();
221
+ }
222
+ const deadline = Date.now() + STARTUP_TIMEOUT_MS;
223
+ for (let i = 0; i < workers.length; i++) {
224
+ while (Atomics.load(ready, i) === 0) {
225
+ const remaining = deadline - Date.now();
226
+ if (remaining <= 0)
227
+ return abandon();
228
+ Atomics.wait(ready, i, 0, remaining);
229
+ }
230
+ }
231
+ return new WorkerFramePool(workers);
232
+ }
233
+ /** Status cell values, for the worker. @internal */
234
+ export const FRAME_STATUS = { PENDING, DONE, FAILED };
235
+ //# sourceMappingURL=frame-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-pool.js","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/frame-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=frame-pool.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-pool.spec.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/frame-pool.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}