@atolljs/core 0.1.1 → 0.1.3

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.
@@ -1,28 +1,218 @@
1
1
  /**
2
- * The SDK's vendored zod surface — everything the contract layer needs,
3
- * narrowed.
2
+ * The SDK's vendored schema engine — the slice of zod v4 the contract layer
3
+ * needs, implemented in-house so zod never lands in the dependency tree.
4
4
  *
5
- * `import { z } from 'zod'` bundles the ENTIRE classic namespace in consumer
6
- * builds (~440KB minified): the `z` object can't be property-shaken, so it
7
- * drags in every locale, the JSON-schema processors, and the compile
8
- * pipeline. Named imports tree-shake (~93KB for the full set below).
5
+ * Schemas carry zod's `_zod.def` shape (`type`, `format`, `checks`,
6
+ * `shape`, `element`) and check defs use zod's names (`greater_than`,
7
+ * `number_format`, `max_length`, `length_equals`, …). The layout compiler
8
+ * reads those fields duck-typed — never `instanceof` — so consumer-supplied
9
+ * classic zod and zod/mini schemas introspect identically: `z.uint32()`,
10
+ * `z.object(...)`, `z.string().meta({ bytes: n })` all still work as
11
+ * members/field schemas.
9
12
  *
10
- * `instanceof` guards use the `$Zod*` base classes from `zod/v4/core` —
11
- * classic AND mini schemas both extend them, so user-supplied schemas match
12
- * either way. Constructors stay classic (`zod` named imports) because `mz`
13
- * output and `memory.schemas` are documented as ordinary zod — `.meta()`,
14
- * `.refine()`, `.parse()` must all work and compose with the consumer's own
15
- * `z.object(...)`.
13
+ * Chain methods mini omits (`.refine()`, `.meta()`, `.max()` …) are
14
+ * re-attached to atoll-minted schemas by `fluent()` — `reef`, `listSchema`,
15
+ * `memory.schemas`. Refines attach via `.check()` so the schema's
16
+ * `def.type` survives — a refined `reef.string` still lays out as a
17
+ * fixed-width string.
16
18
  */
17
- import { array, bigint, boolean, instanceof as instanceof_, int32, int64, float32, float64, number, object, string, uint32, uint64, unknown as unknown_ } from 'zod';
18
- import { $ZodArray, $ZodObject, $ZodString, $ZodType } from 'zod/v4/core';
19
- import type * as zod from 'zod';
19
+ /** Check def payloads mirror zod v4's `_zod.check.def` shapes. */
20
+ export interface CheckDef {
21
+ check: string;
22
+ value?: number | bigint;
23
+ inclusive?: boolean;
24
+ format?: string;
25
+ maximum?: number;
26
+ minimum?: number;
27
+ length?: number;
28
+ }
29
+ export interface Check {
30
+ readonly _zod: {
31
+ readonly def: CheckDef;
32
+ };
33
+ /** Returns `true` or a failure message. */
34
+ evaluate(value: unknown): true | string;
35
+ }
36
+ declare const int: () => Check;
37
+ declare const gte: (value: number | bigint) => Check;
38
+ declare const lte: (value: number | bigint) => Check;
39
+ declare const nonnegative: () => Check;
40
+ declare const refine: (fn: (v: any) => unknown, message?: string) => Check;
41
+ declare const length: (n: number) => Check;
42
+ declare const maxLength: (n: number) => Check;
43
+ declare const minLength: (n: number) => Check;
44
+ export declare const globalRegistry: {
45
+ add(schema: object, meta: Record<string, unknown>): void;
46
+ get(schema: object): Record<string, unknown> | undefined;
47
+ };
48
+ export type Registry = typeof globalRegistry;
49
+ export interface SchemaDef {
50
+ type: string;
51
+ checks?: Check[];
52
+ format?: string;
53
+ shape?: Record<string, ZodLike>;
54
+ element?: ZodLike;
55
+ cls?: abstract new (...args: any[]) => unknown;
56
+ }
57
+ export declare class SchemaError extends Error {
58
+ readonly name = "SchemaError";
59
+ }
60
+ /** The minimal schema shape — satisfied by ours and by real zod schemas. */
61
+ export interface ZodLike<Output = unknown, Input = Output> {
62
+ readonly _zod: {
63
+ readonly output: Output;
64
+ readonly input: Input;
65
+ readonly def: {
66
+ readonly type?: string;
67
+ readonly checks?: readonly unknown[];
68
+ };
69
+ };
70
+ parse(value: unknown): Output;
71
+ safeParse(value: unknown): {
72
+ success: true;
73
+ data: Output;
74
+ } | {
75
+ success: false;
76
+ error: unknown;
77
+ };
78
+ }
79
+ export declare abstract class ZodType<Output = unknown, Input = Output> implements ZodLike<Output, Input> {
80
+ readonly _zod: {
81
+ output: Output;
82
+ input: Input;
83
+ def: SchemaDef;
84
+ };
85
+ constructor(def: SchemaDef);
86
+ /** Base-kind check — subclasses enforce the primitive before checks run. */
87
+ abstract inner(value: unknown): Output;
88
+ parse(value: unknown): Output;
89
+ safeParse(value: unknown): {
90
+ success: true;
91
+ data: Output;
92
+ } | {
93
+ success: false;
94
+ error: unknown;
95
+ };
96
+ /** Returns a new schema with the checks appended (def.type unchanged). */
97
+ check(...checks: Check[]): this;
98
+ register(registry: Registry, meta: Record<string, unknown>): this;
99
+ }
100
+ declare class ZodNumber extends ZodType<number> {
101
+ readonly _zod: {
102
+ output: number;
103
+ input: number;
104
+ def: SchemaDef & {
105
+ type: 'number';
106
+ };
107
+ };
108
+ inner(v: unknown): number;
109
+ }
110
+ declare class ZodString extends ZodType<string> {
111
+ readonly _zod: {
112
+ output: string;
113
+ input: string;
114
+ def: SchemaDef & {
115
+ type: 'string';
116
+ };
117
+ };
118
+ inner(v: unknown): string;
119
+ }
120
+ declare class ZodBoolean extends ZodType<boolean> {
121
+ readonly _zod: {
122
+ output: boolean;
123
+ input: boolean;
124
+ def: SchemaDef & {
125
+ type: 'boolean';
126
+ };
127
+ };
128
+ inner(v: unknown): boolean;
129
+ }
130
+ declare class ZodBigint extends ZodType<bigint> {
131
+ readonly _zod: {
132
+ output: bigint;
133
+ input: bigint;
134
+ def: SchemaDef & {
135
+ type: 'bigint';
136
+ };
137
+ };
138
+ inner(v: unknown): bigint;
139
+ }
140
+ declare class ZodUnknown extends ZodType<unknown> {
141
+ inner(v: unknown): unknown;
142
+ }
143
+ declare class ZodInstanceof<T> extends ZodType<T> {
144
+ inner(v: unknown): T;
145
+ }
146
+ type ShapeOutput<S extends Record<string, ZodLike>> = {
147
+ [K in keyof S]: S[K] extends {
148
+ _zod: {
149
+ output: infer O;
150
+ };
151
+ } ? O : never;
152
+ };
153
+ /** Strips unknown keys like zod's object parse — output is the shape only. */
154
+ declare class ZodObjectSchema<S extends Record<string, ZodLike>> extends ZodType<ShapeOutput<S>> {
155
+ readonly _zod: {
156
+ output: ShapeOutput<S>;
157
+ input: ShapeOutput<S>;
158
+ def: SchemaDef & {
159
+ type: 'object';
160
+ shape: S;
161
+ };
162
+ };
163
+ get shape(): S;
164
+ inner(v: unknown): ShapeOutput<S>;
165
+ }
166
+ declare class ZodArraySchema<E extends ZodLike> extends ZodType<OutputOf<E>[]> {
167
+ readonly _zod: {
168
+ output: OutputOf<E>[];
169
+ input: OutputOf<E>[];
170
+ def: SchemaDef & {
171
+ type: 'array';
172
+ element: E;
173
+ };
174
+ };
175
+ inner(v: unknown): OutputOf<E>[];
176
+ }
177
+ type OutputOf<S> = S extends {
178
+ _zod: {
179
+ output: infer O;
180
+ };
181
+ } ? O : never;
182
+ declare const number: () => ZodNumber;
183
+ declare const string: () => ZodString;
184
+ declare const boolean_: () => ZodBoolean;
185
+ declare const bigint_: () => ZodBigint;
186
+ declare const unknown_: () => ZodUnknown;
187
+ declare const instanceof_: <T extends abstract new (...args: any[]) => any>(cls: T) => ZodInstanceof<InstanceType<T>>;
188
+ declare const object_: <S extends Record<string, ZodLike>>(shape: S) => ZodObjectSchema<S>;
189
+ declare const array: <E extends ZodLike>(element: E) => ZodArraySchema<E>;
190
+ declare const int32: () => ZodNumber;
191
+ declare const uint32: () => ZodNumber;
192
+ declare const float32: () => ZodNumber;
193
+ declare const float64: () => ZodNumber;
194
+ declare const int64: () => ZodBigint;
195
+ declare const uint64: () => ZodBigint;
196
+ /** The chainable spellings re-added to atoll-minted schemas. */
197
+ export type Fluent<S extends ZodLike> = S & {
198
+ /** Custom check via `.check()` — keeps `def.type`, unlike a wrapping refine. */
199
+ refine(fn: (value: S['_zod']['output']) => unknown, params?: string): Fluent<S>;
200
+ /** `meta()` reads, `meta(m)` writes — backed by the module registry. */
201
+ meta(): Record<string, unknown> | undefined;
202
+ meta(m: Record<string, unknown>): Fluent<S>;
203
+ min(value: number | bigint): Fluent<S>;
204
+ max(value: number | bigint): Fluent<S>;
205
+ length(n: number): Fluent<S>;
206
+ int(): Fluent<S>;
207
+ };
208
+ /** Attaches the `Fluent` methods as non-enumerable own properties. */
209
+ export declare function fluent<S extends ZodType>(schema: S): Fluent<S>;
20
210
  export declare const z: {
21
211
  number: typeof number;
22
212
  string: typeof string;
23
- boolean: typeof boolean;
24
- bigint: typeof bigint;
25
- object: typeof object;
213
+ boolean: typeof boolean_;
214
+ bigint: typeof bigint_;
215
+ object: typeof object_;
26
216
  array: typeof array;
27
217
  instanceof: typeof instanceof_;
28
218
  unknown: typeof unknown_;
@@ -32,22 +222,61 @@ export declare const z: {
32
222
  float64: typeof float64;
33
223
  int64: typeof int64;
34
224
  uint64: typeof uint64;
35
- /** Core classes — instanceof-matching for user schemas (classic or mini). */
36
- ZodType: zod.core.$constructor<$ZodType<unknown, unknown, zod.core.$ZodTypeInternals<unknown, unknown>>, zod.core.$ZodTypeDef>;
37
- ZodObject: zod.core.$constructor<$ZodObject<Readonly<Readonly<{
38
- [k: string]: $ZodType<unknown, unknown, zod.core.$ZodTypeInternals<unknown, unknown>>;
39
- }>>, zod.core.$ZodObjectConfig>, zod.core.$ZodObjectDef<Readonly<Readonly<{
40
- [k: string]: $ZodType<unknown, unknown, zod.core.$ZodTypeInternals<unknown, unknown>>;
41
- }>>>>;
42
- ZodArray: zod.core.$constructor<$ZodArray<$ZodType<unknown, unknown, zod.core.$ZodTypeInternals<unknown, unknown>>>, zod.core.$ZodArrayDef<$ZodType<unknown, unknown, zod.core.$ZodTypeInternals<unknown, unknown>>>>;
43
- ZodString: zod.core.$constructor<$ZodString<unknown>, zod.core.$ZodStringDef>;
225
+ int: typeof int;
226
+ gte: typeof gte;
227
+ lte: typeof lte;
228
+ nonnegative: typeof nonnegative;
229
+ refine: typeof refine;
230
+ length: typeof length;
231
+ maxLength: typeof maxLength;
232
+ minLength: typeof minLength;
233
+ globalRegistry: {
234
+ add(schema: object, meta: Record<string, unknown>): void;
235
+ get(schema: object): Record<string, unknown> | undefined;
236
+ };
237
+ /** Base classes — `instanceof` covers atoll-minted schemas. */
238
+ ZodType: typeof ZodType;
239
+ ZodObject: typeof ZodObjectSchema;
240
+ ZodArray: typeof ZodArraySchema;
241
+ ZodString: typeof ZodString;
44
242
  };
45
243
  export declare namespace z {
46
- type ZodTypeAny = zod.ZodTypeAny;
47
- type ZodType<Output = unknown, Input = unknown> = zod.ZodType<Output, Input>;
48
- type ZodString = zod.ZodString;
49
- type ZodArray<T extends zod.ZodTypeAny = zod.ZodTypeAny> = zod.ZodArray<T>;
50
- type ZodObject<S extends zod.ZodRawShape = zod.ZodRawShape> = zod.ZodObject<S>;
51
- type ZodRawShape = zod.ZodRawShape;
52
- type output<T extends zod.ZodTypeAny> = zod.output<T>;
244
+ type ZodTypeAny = ZodLike;
245
+ type ZodType<Output = unknown, Input = unknown> = ZodLike<Output, Input>;
246
+ type ZodRawShape = Record<string, ZodLike>;
247
+ interface ZodObject<S extends ZodRawShape = ZodRawShape> extends ZodLike<ShapeOutput<S>, ShapeOutput<S>> {
248
+ readonly _zod: {
249
+ output: ShapeOutput<S>;
250
+ input: ShapeOutput<S>;
251
+ def: {
252
+ type: 'object';
253
+ shape: S;
254
+ checks?: readonly unknown[];
255
+ };
256
+ };
257
+ }
258
+ interface ZodArray<E extends ZodTypeAny = ZodTypeAny> extends ZodLike<OutputOf<E>[]> {
259
+ readonly _zod: {
260
+ output: OutputOf<E>[];
261
+ input: OutputOf<E>[];
262
+ def: {
263
+ type: 'array';
264
+ element: E;
265
+ checks?: readonly unknown[];
266
+ };
267
+ };
268
+ }
269
+ interface ZodString extends ZodLike<string> {
270
+ readonly _zod: {
271
+ output: string;
272
+ input: string;
273
+ def: {
274
+ type: 'string';
275
+ checks?: readonly unknown[];
276
+ };
277
+ };
278
+ }
279
+ type ZodMiniObject<S extends ZodRawShape = ZodRawShape> = ZodObject<S>;
280
+ type output<T extends ZodTypeAny> = OutputOf<T>;
53
281
  }
282
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export { bindSharedMemories, defineSharedMemory, field, getDefinedSharedMemoryCount, jsonCodec, registerConnectorFactory } from './contract/sharedMemory';
2
- export { mz } from './contract/mz';
2
+ export { reef } from './contract/reef';
3
3
  export type { Codec, Connector, ConnectorContext, ConnectorFactory, FieldDescriptor, FieldGroup, FieldSchema, FixedArrayDescriptor, FixedObjectDescriptor, FlatKey, InferField, PathConnector, SpecPath, SpecSchemas, SharedAccess, SharedMemory, SharedMemoryOptions, SharedSpec, ScalarKind, ListConnector, ListDescriptor, ListFieldSpec, ListFields, ListMember, ListRecord, ListSpec, } from './contract/sharedMemory';
4
- export { msgpackCodec } from './contract/msgpackCodec';
5
4
  export { msgpackrCodec } from './contract/msgpackrCodec';
6
5
  export { listSchema } from './contract/listSchema';
7
6
  export type { ListZodShape } from './contract/listSchema';
package/dist/index.js CHANGED
@@ -2,18 +2,17 @@ import { msgpackrCodec as e } from "./index2.js";
2
2
  import { listSchema as t } from "./index4.js";
3
3
  import { getLogLevel as n, log as r, scoped as i, setLogLevel as a, setLogSink as o } from "./index5.js";
4
4
  import { bindSharedMemories as s, defineSharedMemory as c, field as l, getDefinedSharedMemoryCount as u, jsonCodec as d, registerConnectorFactory as f } from "./index6.js";
5
- import { mz as p } from "./index7.js";
6
- import { msgpackCodec as m } from "./index8.js";
7
- import { MemoryManager as h } from "./index9.js";
8
- import { PoolQueueFullError as g, TaskAbortedError as _, TaskTimeoutError as v, WorkerCrashedError as y } from "./index10.js";
9
- import { WorkerPool as b } from "./index11.js";
10
- import { connectWorker as x, workerClient as S } from "./index12.js";
11
- import { connectSharedWorker as C } from "./index13.js";
12
- import { TaskRegistry as w } from "./index14.js";
13
- import { sharedWorkerHost as T } from "./index15.js";
14
- import { createClient as E, defineService as D, implementService as O, rpc as k, serviceMethod as A } from "./index16.js";
15
- import { RESERVED_CLIENT_KEYS as j, defineWorker as M } from "./index18.js";
16
- import { reactive as N, shallowEqual as P, watch as F } from "./index19.js";
17
- import { observe as I } from "./index20.js";
18
- import { defineTask as L, isAsyncTask as R, toTask as z } from "./index21.js";
19
- export { h as MemoryManager, g as PoolQueueFullError, j as RESERVED_CLIENT_KEYS, _ as TaskAbortedError, w as TaskRegistry, v as TaskTimeoutError, y as WorkerCrashedError, b as WorkerPool, s as bindSharedMemories, C as connectSharedWorker, x as connectWorker, E as createClient, D as defineService, c as defineSharedMemory, L as defineTask, M as defineWorker, l as field, u as getDefinedSharedMemoryCount, n as getLogLevel, O as implementService, R as isAsyncTask, d as jsonCodec, t as listSchema, r as log, m as msgpackCodec, e as msgpackrCodec, p as mz, I as observe, N as reactive, f as registerConnectorFactory, k as rpc, i as scoped, A as serviceMethod, a as setLogLevel, o as setLogSink, P as shallowEqual, T as sharedWorkerHost, z as toTask, F as watch, S as workerClient };
5
+ import { reef as p } from "./index7.js";
6
+ import { MemoryManager as m } from "./index8.js";
7
+ import { PoolQueueFullError as h, TaskAbortedError as g, TaskTimeoutError as _, WorkerCrashedError as v } from "./index9.js";
8
+ import { WorkerPool as y } from "./index10.js";
9
+ import { connectWorker as b, workerClient as x } from "./index11.js";
10
+ import { connectSharedWorker as S } from "./index12.js";
11
+ import { TaskRegistry as C } from "./index13.js";
12
+ import { sharedWorkerHost as w } from "./index14.js";
13
+ import { createClient as T, defineService as E, implementService as D, rpc as O, serviceMethod as k } from "./index15.js";
14
+ import { RESERVED_CLIENT_KEYS as A, defineWorker as j } from "./index17.js";
15
+ import { reactive as M, shallowEqual as N, watch as P } from "./index18.js";
16
+ import { observe as F } from "./index19.js";
17
+ import { defineTask as I, isAsyncTask as L, toTask as R } from "./index20.js";
18
+ export { m as MemoryManager, h as PoolQueueFullError, A as RESERVED_CLIENT_KEYS, g as TaskAbortedError, C as TaskRegistry, _ as TaskTimeoutError, v as WorkerCrashedError, y as WorkerPool, s as bindSharedMemories, S as connectSharedWorker, b as connectWorker, T as createClient, E as defineService, c as defineSharedMemory, I as defineTask, j as defineWorker, l as field, u as getDefinedSharedMemoryCount, n as getLogLevel, D as implementService, L as isAsyncTask, d as jsonCodec, t as listSchema, r as log, e as msgpackrCodec, F as observe, M as reactive, p as reef, f as registerConnectorFactory, O as rpc, i as scoped, k as serviceMethod, a as setLogLevel, o as setLogSink, N as shallowEqual, w as sharedWorkerHost, R as toTask, P as watch, x as workerClient };
package/dist/index10.js CHANGED
@@ -1,22 +1,193 @@
1
- //#region src/pool/errors.ts
2
- var e = class extends Error {
3
- constructor(e = "WorkerPool task queue is full") {
4
- super(e), this.name = "PoolQueueFullError";
1
+ import { fmtBytes as e, scoped as t } from "./index5.js";
2
+ import { MemoryManager as n } from "./index8.js";
3
+ import { PoolQueueFullError as r, TaskAbortedError as i, TaskTimeoutError as a, WorkerCrashedError as o } from "./index9.js";
4
+ //#region src/pool/workerPool.ts
5
+ var s = t("pool"), c = t("task"), l = () => ({
6
+ count: 0,
7
+ mean: 0,
8
+ max: 0,
9
+ add(e) {
10
+ this.count++, this.mean += (e - this.mean) / this.count, e > this.max && (this.max = e);
5
11
  }
6
- }, t = class extends Error {
7
- constructor(e = "task aborted") {
8
- super(e), this.name = "AbortError";
12
+ }), u = class {
13
+ slots = [];
14
+ pending = /* @__PURE__ */ new Map();
15
+ nextMessageId = 0;
16
+ queue = [];
17
+ memoryManager;
18
+ workerUrl;
19
+ spawn;
20
+ concurrency;
21
+ maxQueue;
22
+ respawn;
23
+ taskTimeout;
24
+ closed = !1;
25
+ drainWaiters = [];
26
+ statsAgg = {
27
+ completed: 0,
28
+ failed: 0,
29
+ aborted: 0,
30
+ waitMs: l(),
31
+ runMs: l()
32
+ };
33
+ sharedMemory;
34
+ persistence;
35
+ constructor(t) {
36
+ if (t.sharedMemory && (typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated)) throw Error("WorkerPool requires SharedArrayBuffer in a cross-origin isolated context — serve the page with COOP/COEP headers.");
37
+ if (!t.workerUrl && !t.createWorker) throw Error("WorkerPool requires either `workerUrl` or `createWorker` in its config.");
38
+ this.workerUrl = t.workerUrl, this.spawn = t.createWorker ?? (() => new Worker(this.workerUrl, { type: "module" })), this.concurrency = t.concurrency ?? 1, this.maxQueue = t.maxQueue ?? Infinity, this.respawn = t.respawn ?? !0, this.taskTimeout = t.taskTimeout, t.sharedMemory && (this.sharedMemory = t.sharedMemory, this.memoryManager = new n(t.memory), this.memoryManager.ensureCapacity(this.sharedMemory.totalBytes), this.sharedMemory.bind(this.memoryManager.getBuffer()), this.persistence = t.persistence?.(t.sharedMemory));
39
+ let r = t.poolSize ?? "auto", i = r === "auto" ? navigator.hardwareConcurrency ?? 4 : r;
40
+ s.info(this.sharedMemory ? `spawning ${i} worker(s) with ${e(this.sharedMemory.totalBytes)} shared buffer` : `spawning ${i} worker(s), message-only`, { workerUrl: t.workerUrl ? String(t.workerUrl) : "createWorker()" }), s.debug("tip: setLogLevel('trace') for per-task detail");
41
+ for (let e = 0; e < i; e++) this.addWorker(this.spawn());
42
+ let a = t.tasks ?? {};
43
+ for (let [e, t] of Object.entries(a)) {
44
+ if (e in this) {
45
+ s.warn(`task "${e}" collides with a WorkerPool member — not installed`);
46
+ continue;
47
+ }
48
+ this[e] = (...e) => this.runTask(t, ...e);
49
+ }
50
+ Object.keys(a).length > 0 && s.info(`task methods: ${Object.keys(a).join(", ")}`);
9
51
  }
10
- }, n = class extends Error {
11
- constructor(e = "task timed out") {
12
- super(e), this.name = "TaskTimeoutError";
52
+ addWorker(e) {
53
+ let t = {
54
+ worker: e,
55
+ inFlight: 0
56
+ };
57
+ return e.addEventListener("message", (e) => {
58
+ this.handleReply(t, e.data);
59
+ }), e.addEventListener("error", (e) => {
60
+ this.handleWorkerError(t, e);
61
+ }), this.memoryManager ? e.postMessage({
62
+ type: "INIT_MEMORY",
63
+ memory: this.memoryManager.memory
64
+ }) : e.postMessage({ type: "INIT" }), this.slots.push(t), s.debug(`worker spawned, ${this.memoryManager ? "INIT_MEMORY" : "INIT"} sent`), t;
13
65
  }
14
- }, r = class extends Error {
15
- constructor(e = "worker crashed") {
16
- super(e), this.name = "WorkerCrashedError";
66
+ handleReply(e, t) {
67
+ let n = t.messageId === void 0 ? void 0 : this.pending.get(t.messageId);
68
+ n && (this.pending.delete(t.messageId), e.inFlight--, this.detach(n), n.done || (n.done = !0, this.statsAgg.runMs.add(performance.now() - (n.sentAt ?? n.enqueuedAt)), t.success ? (this.statsAgg.completed++, c.debug(`← ${n.contract.taskId} ok`), n.resolve(t.result)) : (this.statsAgg.failed++, c.warn(`← ${n.contract.taskId} failed: ${t.error}`), n.reject(Error(t.error)))), this.drainQueue(), this.checkDrained());
69
+ }
70
+ handleWorkerError(e, t) {
71
+ if (this.closed) return;
72
+ let n = t, r = n?.message ?? (n?.error ? String(n.error) : "worker error");
73
+ s.warn(`worker error: ${r}`);
74
+ for (let [t, n] of [...this.pending]) if (n.slot === e) {
75
+ if (this.pending.delete(t), this.detach(n), n.done) continue;
76
+ n.done = !0, this.statsAgg.failed++, n.reject(new o(r));
77
+ }
78
+ let i = this.slots.indexOf(e);
79
+ if (i >= 0 && this.slots.splice(i, 1), e.worker.terminate(), this.respawn) s.info("respawning crashed worker"), this.addWorker(this.spawn());
80
+ else if (this.slots.length === 0) for (let e of this.queue.splice(0)) e.done = !0, this.detach(e), this.statsAgg.failed++, e.reject(new o(r));
81
+ this.drainQueue(), this.checkDrained();
82
+ }
83
+ pickWorker() {
84
+ let e;
85
+ for (let t of this.slots) t.inFlight >= this.concurrency || (!e || t.inFlight < e.inFlight) && (e = t);
86
+ return e;
87
+ }
88
+ drainQueue() {
89
+ let e;
90
+ for (; this.queue.length > 0 && (e = this.pickWorker());) {
91
+ let t = this.queue.shift();
92
+ t.done || this.send(e, t);
93
+ }
94
+ }
95
+ send(e, t) {
96
+ let n = this.nextMessageId++;
97
+ t.messageId = n, t.slot = e, t.sentAt = performance.now(), this.statsAgg.waitMs.add(performance.now() - t.enqueuedAt), e.inFlight++, this.pending.set(n, t), c.debug(`→ ${t.contract.taskId}`, {
98
+ worker: this.slots.indexOf(e),
99
+ args: t.args
100
+ }), e.worker.postMessage({
101
+ type: "EXECUTE_TASK",
102
+ messageId: n,
103
+ taskId: t.contract.taskId,
104
+ args: t.args
105
+ });
106
+ }
107
+ detach(e) {
108
+ e.timer && clearTimeout(e.timer), e.signal && e.onSignalAbort && e.signal.removeEventListener("abort", e.onSignalAbort);
109
+ }
110
+ cancel(e, t) {
111
+ if (e.done) return;
112
+ let n = this.queue.indexOf(e);
113
+ n >= 0 && this.queue.splice(n, 1), e.done = !0, this.detach(e), this.statsAgg.aborted++, e.reject(t), this.drainQueue(), this.checkDrained();
114
+ }
115
+ checkDrained() {
116
+ if (this.queue.length === 0 && this.pending.size === 0) {
117
+ let e = this.drainWaiters.splice(0);
118
+ for (let t of e) t();
119
+ }
120
+ }
121
+ dispatch(e, t, n) {
122
+ return this.closed || this.slots.length === 0 ? Promise.reject(new o("WorkerPool has been terminated — no workers available.")) : n?.signal?.aborted ? Promise.reject(new i()) : new Promise((o, s) => {
123
+ let c = {
124
+ contract: e,
125
+ args: t,
126
+ enqueuedAt: performance.now(),
127
+ resolve: o,
128
+ reject: s,
129
+ done: !1,
130
+ signal: n?.signal
131
+ };
132
+ n?.signal && (c.onSignalAbort = () => this.cancel(c, new i()), n.signal.addEventListener("abort", c.onSignalAbort, { once: !0 }));
133
+ let l = n?.timeout ?? this.taskTimeout;
134
+ l !== void 0 && (c.timer = setTimeout(() => this.cancel(c, new a()), l));
135
+ let u = this.pickWorker();
136
+ if (u) this.send(u, c);
137
+ else if (this.queue.length >= this.maxQueue) {
138
+ c.done = !0, this.detach(c), s(new r());
139
+ return;
140
+ } else this.queue.push(c);
141
+ });
142
+ }
143
+ runTask(e, ...t) {
144
+ return this.dispatch(e, t);
145
+ }
146
+ get sharedBuffer() {
147
+ return this.memoryManager?.getBuffer();
148
+ }
149
+ get workers() {
150
+ return this.slots.map((e) => e.worker);
151
+ }
152
+ stats() {
153
+ return {
154
+ workers: this.slots.length,
155
+ idle: this.slots.filter((e) => e.inFlight === 0).length,
156
+ inFlight: this.pending.size,
157
+ queued: this.queue.length,
158
+ completed: this.statsAgg.completed,
159
+ failed: this.statsAgg.failed,
160
+ aborted: this.statsAgg.aborted,
161
+ waitMs: {
162
+ count: this.statsAgg.waitMs.count,
163
+ mean: this.statsAgg.waitMs.mean,
164
+ max: this.statsAgg.waitMs.max
165
+ },
166
+ runMs: {
167
+ count: this.statsAgg.runMs.count,
168
+ mean: this.statsAgg.runMs.mean,
169
+ max: this.statsAgg.runMs.max
170
+ }
171
+ };
172
+ }
173
+ close() {
174
+ return this.queue.length === 0 && this.pending.size === 0 ? (this.terminate(), Promise.resolve()) : new Promise((e) => {
175
+ this.drainWaiters.push(() => {
176
+ this.terminate(), e();
177
+ });
178
+ });
179
+ }
180
+ terminate() {
181
+ this.closed = !0, this.persistence?.stop()?.catch?.((e) => s.warn("memory persistence stop failed", e)), s.info(`terminating ${this.slots.length} worker(s)`);
182
+ let e = new o("pool terminated");
183
+ for (let [, t] of this.pending) this.detach(t), !t.done && (t.done = !0, this.statsAgg.failed++, t.reject(e));
184
+ this.pending.clear();
185
+ for (let t of this.queue.splice(0)) t.done = !0, this.detach(t), this.statsAgg.failed++, t.reject(e);
186
+ for (let e of this.slots) e.worker.terminate();
187
+ this.slots = [], this.checkDrained();
17
188
  }
18
189
  };
19
190
  //#endregion
20
- export { e as PoolQueueFullError, t as TaskAbortedError, n as TaskTimeoutError, r as WorkerCrashedError };
191
+ export { u as WorkerPool };
21
192
 
22
193
  //# sourceMappingURL=index10.js.map