@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.
- package/LICENSE +21 -0
- package/README.md +27 -22
- package/dist/contract/listSchema.d.ts +4 -4
- package/dist/contract/reef.d.ts +377 -0
- package/dist/contract/sharedMemory.d.ts +13 -13
- package/dist/contract/zod.d.ts +263 -34
- package/dist/index.d.ts +1 -2
- package/dist/index.js +14 -15
- package/dist/index10.js +185 -14
- package/dist/index11.js +47 -188
- package/dist/index12.js +59 -45
- package/dist/index13.js +19 -58
- package/dist/index14.js +60 -24
- package/dist/index15.js +43 -56
- package/dist/index16.js +41 -45
- package/dist/index17.js +38 -42
- package/dist/index18.js +54 -35
- package/dist/index19.js +46 -51
- package/dist/index20.js +50 -47
- package/dist/index3.js +199 -22
- package/dist/index4.js +66 -61
- package/dist/index6.js +84 -84
- package/dist/index7.js +19 -19
- package/dist/index8.js +33 -6
- package/dist/index9.js +14 -29
- package/package.json +12 -8
- package/src/contract/listSchema.ts +51 -29
- package/src/contract/reef.ts +62 -0
- package/src/contract/sharedMemory.ts +25 -25
- package/src/contract/zod.ts +344 -32
- package/src/index.ts +1 -2
- package/dist/contract/msgpackCodec.d.ts +0 -7
- package/dist/contract/mz.d.ts +0 -43
- package/dist/index21.js +0 -59
- package/src/contract/msgpackCodec.ts +0 -9
- package/src/contract/mz.ts +0 -48
package/dist/contract/zod.d.ts
CHANGED
|
@@ -1,28 +1,218 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The SDK's vendored
|
|
3
|
-
*
|
|
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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
24
|
-
bigint: typeof
|
|
25
|
-
object: typeof
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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 =
|
|
47
|
-
type ZodType<Output = unknown, Input = unknown> =
|
|
48
|
-
type
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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 {
|
|
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 {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
},
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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 {
|
|
191
|
+
export { u as WorkerPool };
|
|
21
192
|
|
|
22
193
|
//# sourceMappingURL=index10.js.map
|