@atolljs/core 0.1.14 → 0.1.15

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 (40) hide show
  1. package/dist/contract/listSchema.js +1 -2
  2. package/dist/contract/memoryDevtools.js +2 -3
  3. package/dist/contract/msgpackrCodec.js +1 -2
  4. package/dist/contract/reef.js +1 -2
  5. package/dist/contract/sharedMemory.js +61 -62
  6. package/dist/contract/types.d.ts +24 -0
  7. package/dist/contract/zod.js +1 -2
  8. package/dist/devtools.js +32 -39
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +22 -22
  11. package/dist/log.js +1 -2
  12. package/dist/observable.js +18 -19
  13. package/dist/pool/dedicatedWorker.d.ts +3 -0
  14. package/dist/pool/dedicatedWorker.js +72 -68
  15. package/dist/pool/devtoolsCommands.js +1 -2
  16. package/dist/pool/errors.js +1 -2
  17. package/dist/pool/memory.js +1 -2
  18. package/dist/pool/subWorkerClient.js +1 -2
  19. package/dist/pool/workerChannel.js +21 -22
  20. package/dist/pool/workerClient.d.ts +15 -1
  21. package/dist/pool/workerClient.js +14 -10
  22. package/dist/pool/workerPool.d.ts +3 -0
  23. package/dist/pool/workerPool.js +119 -121
  24. package/dist/reactive.js +1 -2
  25. package/dist/reactiveGraph.js +1 -2
  26. package/dist/service.js +1 -2
  27. package/dist/shared/sharedWorkerClient.js +2 -9
  28. package/dist/shared/sharedWorkerHost.js +22 -27
  29. package/dist/task.js +1 -2
  30. package/dist/testing/inProcessWorker.js +3 -8
  31. package/dist/userTiming.js +1 -2
  32. package/dist/worker/defineWorker.js +8 -9
  33. package/dist/worker/registry.js +1 -2
  34. package/dist/worker/workerBootstrap.js +40 -52
  35. package/package.json +11 -7
  36. package/src/contract/types.ts +26 -0
  37. package/src/index.ts +2 -0
  38. package/src/pool/dedicatedWorker.ts +19 -1
  39. package/src/pool/workerClient.ts +30 -1
  40. package/src/pool/workerPool.ts +11 -1
@@ -1,5 +1,5 @@
1
1
  import { fluent as e, z as t } from "./zod.js";
2
- //#region src/contract/listSchema.ts
2
+ // src/contract/listSchema.ts
3
3
  var n = new TextEncoder(), r = (n, r) => e(t.number().check(t.int(), t.gte(n), t.lte(r))), i = {
4
4
  i8: r(-128, 127),
5
5
  u8: r(0, 255),
@@ -121,5 +121,4 @@ function _(e) {
121
121
  function v(e) {
122
122
  return !s(e) || e._zod.def.type !== "string" ? null : _(e);
123
123
  }
124
- //#endregion
125
124
  export { o as listSchema, m as memberToSpec, g as zodArrayInfo, h as zodObjectShape, v as zodStringBytes };
@@ -1,5 +1,5 @@
1
1
  import { emitDevtools as e, previewValue as t, registerDevtoolsCommand as n } from "../devtools.js";
2
- //#region src/contract/memoryDevtools.ts
2
+ // src/contract/memoryDevtools.ts
3
3
  var r = /* @__PURE__ */ new Map(), i = () => [], a = !1, o = 5, s = 16, c = (e) => {
4
4
  let n = e;
5
5
  if (typeof n.readAt == "function" && typeof n.recordCount == "number") {
@@ -114,7 +114,7 @@ var r = /* @__PURE__ */ new Map(), i = () => [], a = !1, o = 5, s = 16, c = (e)
114
114
  rule: t.rule.text,
115
115
  hits: t.hits
116
116
  })), v = (e) => {
117
- i = e, !a && (a = !0, n("memory.read", () => {
117
+ i = e, a || (a = !0, n("memory.read", () => {
118
118
  let e = [];
119
119
  return i().forEach((t, n) => {
120
120
  if (t.bound) for (let { path: r } of t.fields()) try {
@@ -159,5 +159,4 @@ var r = /* @__PURE__ */ new Map(), i = () => [], a = !1, o = 5, s = 16, c = (e)
159
159
  return r.get(t)?.stop(), r.delete(t), _();
160
160
  }), n("memory.watches", () => _()));
161
161
  };
162
- //#endregion
163
162
  export { h as checkWatchOnWrite, v as ensureMemoryCommands, c as fieldPreview, r as memoryWatches, p as parseWatchRule };
@@ -1,8 +1,7 @@
1
1
  import { Packr as e } from "msgpackr";
2
- //#region src/contract/msgpackrCodec.ts
2
+ // src/contract/msgpackrCodec.ts
3
3
  var t = new e({ useRecords: !0 }), n = {
4
4
  encode: (e) => t.pack(e),
5
5
  decode: (e) => t.unpack(e)
6
6
  };
7
- //#endregion
8
7
  export { n as msgpackrCodec };
@@ -1,5 +1,5 @@
1
1
  import { fluent as e, z as t } from "./zod.js";
2
- //#region src/contract/reef.ts
2
+ // src/contract/reef.ts
3
3
  var n = new TextEncoder(), r = {
4
4
  i8: () => e(t.number().check(t.int(), t.gte(-128), t.lte(127))),
5
5
  u8: () => e(t.number().check(t.int(), t.gte(0), t.lte(255))),
@@ -17,5 +17,4 @@ var n = new TextEncoder(), r = {
17
17
  object: (n) => e(t.object(n)),
18
18
  array: (n) => e(t.array(n))
19
19
  };
20
- //#endregion
21
20
  export { r as reef };
@@ -1,11 +1,11 @@
1
- import { fluent as e, z as t } from "./zod.js";
2
- import { memberToSpec as n, zodArrayInfo as r, zodObjectShape as i, zodStringBytes as a } from "./listSchema.js";
3
- import { devtoolsEnabled as o, emitDevtools as s } from "../devtools.js";
4
- import { checkWatchOnWrite as c, ensureMemoryCommands as l, memoryWatches as u } from "./memoryDevtools.js";
5
- import { msgpackrCodec as d } from "./msgpackrCodec.js";
6
- import { fmtBytes as f, scoped as p } from "../log.js";
7
- //#region src/contract/sharedMemory.ts
8
- var m = p("memory"), h = 8, g = (e, t) => e + t - 1 & ~(t - 1), _ = (e) => g(e, h), v = (e) => typeof e == "object" && !!e && typeof e.kind == "string" && typeof e.byteLength == "number";
1
+ import { msgpackrCodec as e } from "./msgpackrCodec.js";
2
+ import { memberToSpec as t, zodArrayInfo as n, zodObjectShape as r, zodStringBytes as i } from "./listSchema.js";
3
+ import { devtoolsEnabled as a, emitDevtools as o } from "../devtools.js";
4
+ import { checkWatchOnWrite as s, ensureMemoryCommands as c, memoryWatches as l } from "./memoryDevtools.js";
5
+ import { fmtBytes as u, scoped as d } from "../log.js";
6
+ import { fluent as f, z as p } from "./zod.js";
7
+ // src/contract/sharedMemory.ts
8
+ var m = d("memory"), h = 8, g = (e, t) => e + t - 1 & ~(t - 1), _ = (e) => g(e, h), v = (e) => typeof e == "object" && !!e && typeof e.kind == "string" && typeof e.byteLength == "number";
9
9
  function y(e) {
10
10
  let t = [];
11
11
  for (let [n, r] of Object.entries(e)) if (v(r)) t.push({
@@ -41,14 +41,14 @@ var T = {
41
41
  u64: 8
42
42
  }, E = (e) => typeof e == "string" ? T[e] : "string" in e ? e.string : 1, D = (e) => typeof e == "string" ? T[e] : 1;
43
43
  function O(e) {
44
- let t = {}, r = {}, i = 0;
44
+ let n = {}, r = {}, i = 0;
45
45
  for (let a of Object.keys(e)) {
46
- let o = n(e[a], String(a));
47
- r[a] = o, i = g(i, D(o)), t[a] = i, i += E(o);
46
+ let o = t(e[a], String(a));
47
+ r[a] = o, i = g(i, D(o)), n[a] = i, i += E(o);
48
48
  }
49
49
  return {
50
50
  layout: r,
51
- offsets: t,
51
+ offsets: n,
52
52
  recordSize: _(i)
53
53
  };
54
54
  }
@@ -68,7 +68,7 @@ var k = {
68
68
  byteLength: 4 + n,
69
69
  schema: t
70
70
  };
71
- let r = t ? a(t) : null;
71
+ let r = t ? i(t) : null;
72
72
  if (r !== null) return {
73
73
  kind: "string",
74
74
  byteLength: 4 + r,
@@ -79,7 +79,7 @@ var k = {
79
79
  object: (e) => {
80
80
  let { schema: t, maxBytes: n } = e;
81
81
  if (n === void 0 && t) {
82
- let e = i(t);
82
+ let e = r(t);
83
83
  if (e) {
84
84
  let { layout: n, offsets: r, recordSize: i } = O(e);
85
85
  return {
@@ -101,23 +101,23 @@ var k = {
101
101
  };
102
102
  },
103
103
  array: (e) => {
104
- let { schema: t, maxBytes: i } = e;
105
- if (i === void 0 && t) {
106
- let e = r(t);
104
+ let { schema: r, maxBytes: i } = e;
105
+ if (i === void 0 && r) {
106
+ let e = n(r);
107
107
  if (e) {
108
108
  if (e.capacity === null) throw TypeError("field.array: z.array() needs .max(n) or .length(n) — bounded arrays are fixed-width");
109
- let r;
109
+ let n;
110
110
  try {
111
- r = n(e.element, "array element");
111
+ n = t(e.element, "array element");
112
112
  } catch (e) {
113
113
  throw TypeError(`field.array: element isn't a fixed-width member — use field.list for arrays of records (${e.message})`);
114
114
  }
115
- let i = g(E(r), D(r));
115
+ let i = g(E(n), D(n));
116
116
  return {
117
117
  kind: "array",
118
118
  byteLength: 8 + e.capacity * i,
119
- schema: t,
120
- element: r,
119
+ schema: r,
120
+ element: n,
121
121
  elementStride: i,
122
122
  capacity: e.capacity
123
123
  };
@@ -128,7 +128,7 @@ var k = {
128
128
  return {
129
129
  kind: "array",
130
130
  byteLength: 4 + i,
131
- schema: t
131
+ schema: r
132
132
  };
133
133
  },
134
134
  int32Array: ({ length: e }) => ({
@@ -148,14 +148,14 @@ var k = {
148
148
  byteLength: e
149
149
  }),
150
150
  list: ({ schema: e, count: t }) => {
151
- let n = i(e);
151
+ let n = r(e);
152
152
  if (!n) throw TypeError("field.list: schema must be a reef.object() of fixed-width members");
153
- let { layout: r, offsets: a, recordSize: o } = O(n);
153
+ let { layout: i, offsets: a, recordSize: o } = O(n);
154
154
  return {
155
155
  kind: "list",
156
156
  byteLength: o * t,
157
157
  schema: e,
158
- layout: r,
158
+ layout: i,
159
159
  offsets: a,
160
160
  recordSize: o,
161
161
  count: t
@@ -348,22 +348,22 @@ var M = (e, t, n) => {
348
348
  };
349
349
  w("object", M), w("array", M);
350
350
  function N(e, t, n) {
351
- let r = e, { offsets: i, recordSize: a, count: c } = r, l = j(t).compile(r.layout, i), u = (e) => {
351
+ let r = e, { offsets: i, recordSize: s, count: c } = r, l = j(t).compile(r.layout, i), u = (e) => {
352
352
  if (e < 0 || e >= c) throw RangeError(`Record index ${e} out of bounds (0..${c - 1})`);
353
- }, d = (e, t = {}, r) => (u(e), l.read(n + e * a, t, r)), f = (e, t, r) => {
354
- u(e), l.write(n + e * a, t, r);
353
+ }, d = (e, t = {}, r) => (u(e), l.read(n + e * s, t, r)), f = (e, t, r) => {
354
+ u(e), l.write(n + e * s, t, r);
355
355
  };
356
356
  return {
357
357
  byteOffset: n,
358
358
  byteLength: e.byteLength,
359
359
  recordCount: c,
360
- recordSize: a,
360
+ recordSize: s,
361
361
  readAt: d,
362
362
  writeAt: f,
363
363
  commit: () => {
364
364
  if (t.version) {
365
365
  let e = Atomics.add(t.version.view, t.version.index, 1);
366
- Atomics.notify(t.version.view, t.version.index), t.path && o() && s({
366
+ Atomics.notify(t.version.view, t.version.index), t.path && a() && o({
367
367
  type: "memory:write",
368
368
  path: t.path,
369
369
  version: e + 1
@@ -384,17 +384,17 @@ function F(e) {
384
384
  for (let [n, r] of Object.entries(e)) t[n] = v(r) ? I(r) : Object.fromEntries(Object.entries(r).map(([e, t]) => [e, I(t)]));
385
385
  return t;
386
386
  }
387
- function I(n) {
388
- if (n.schema) return n.schema;
389
- switch (n.kind) {
390
- case "number": return e(t.number());
391
- case "boolean": return e(t.boolean());
392
- case "string": return e(t.string());
393
- case "Int32": return e(t.instanceof(Int32Array));
394
- case "Float64": return e(t.instanceof(Float64Array));
395
- case "BigInt64": return e(t.instanceof(BigInt64Array));
396
- case "Uint8": return e(t.instanceof(Uint8Array));
397
- default: return e(t.unknown());
387
+ function I(e) {
388
+ if (e.schema) return e.schema;
389
+ switch (e.kind) {
390
+ case "number": return f(p.number());
391
+ case "boolean": return f(p.boolean());
392
+ case "string": return f(p.string());
393
+ case "Int32": return f(p.instanceof(Int32Array));
394
+ case "Float64": return f(p.instanceof(Float64Array));
395
+ case "BigInt64": return f(p.instanceof(BigInt64Array));
396
+ case "Uint8": return f(p.instanceof(Uint8Array));
397
+ default: return f(p.unknown());
398
398
  }
399
399
  }
400
400
  var L = class {
@@ -410,12 +410,12 @@ var L = class {
410
410
  boundListeners = /* @__PURE__ */ new Set();
411
411
  isBound = !1;
412
412
  boundBuffer;
413
- constructor(e, t = {}) {
414
- this.spec = e, this.codec = t.codec ?? d, this.plugins = t.plugins, this.entries = y(e), this.schemas = F(e);
415
- let n = 0;
416
- for (let { path: e, descriptor: t } of this.entries) n = _(n), this.offsets.set(e, n), n += t.byteLength;
417
- this.versionOffset = _(n), this.totalBytes = this.versionOffset + _(this.entries.length * 4), P.push(this), m.info(`contract defined: ${this.entries.length} field(s), ${f(this.totalBytes)}`, {
418
- fields: Object.fromEntries(this.entries.map((e) => [e.path, `${e.descriptor.kind}@${this.offsets.get(e.path)?.toLocaleString()}+${f(e.descriptor.byteLength)}`])),
413
+ constructor(t, n = {}) {
414
+ this.spec = t, this.codec = n.codec ?? e, this.plugins = n.plugins, this.entries = y(t), this.schemas = F(t);
415
+ let r = 0;
416
+ for (let { path: e, descriptor: t } of this.entries) r = _(r), this.offsets.set(e, r), r += t.byteLength;
417
+ this.versionOffset = _(r), this.totalBytes = this.versionOffset + _(this.entries.length * 4), P.push(this), m.info(`contract defined: ${this.entries.length} field(s), ${u(this.totalBytes)}`, {
418
+ fields: Object.fromEntries(this.entries.map((e) => [e.path, `${e.descriptor.kind}@${this.offsets.get(e.path)?.toLocaleString()}+${u(e.descriptor.byteLength)}`])),
419
419
  pluginOverrides: Object.keys(this.plugins ?? {})
420
420
  });
421
421
  }
@@ -423,10 +423,10 @@ var L = class {
423
423
  this.connectors.clear();
424
424
  let t = new Int32Array(e, this.versionOffset, this.entries.length);
425
425
  this.entries.forEach(({ path: n, descriptor: r }, i) => {
426
- let a = this.plugins?.[r.kind] ?? C.get(r.kind);
427
- if (!a) throw Error(`Unknown shared memory field kind: ${r.kind}`);
428
- m.debug(`bind "${n}" (${r.kind}, ${f(r.byteLength)}) via ${this.plugins?.[r.kind] ? "plugin" : "built-in"} factory`);
429
- let l = a(r, {
426
+ let c = this.plugins?.[r.kind] ?? C.get(r.kind);
427
+ if (!c) throw Error(`Unknown shared memory field kind: ${r.kind}`);
428
+ m.debug(`bind "${n}" (${r.kind}, ${u(r.byteLength)}) via ${this.plugins?.[r.kind] ? "plugin" : "built-in"} factory`);
429
+ let d = c(r, {
430
430
  buffer: e,
431
431
  codec: this.codec,
432
432
  version: {
@@ -434,20 +434,20 @@ var L = class {
434
434
  index: i
435
435
  },
436
436
  path: n
437
- }, this.offsets.get(n)), d = l.commit;
437
+ }, this.offsets.get(n)), f = d.commit;
438
438
  this.connectors.set(n, {
439
- ...l,
439
+ ...d,
440
440
  write: (e) => {
441
- l.write(e);
441
+ d.write(e);
442
442
  let r = Atomics.add(t, i, 1);
443
- Atomics.notify(t, i), o() && (s({
443
+ Atomics.notify(t, i), a() && (o({
444
444
  type: "memory:write",
445
445
  path: n,
446
446
  version: r + 1
447
- }), u.size && c(this, n, r + 1));
447
+ }), l.size && s(this, n, r + 1));
448
448
  },
449
- ...d && o() ? { commit: () => {
450
- d(), u.size && c(this, n, Atomics.load(t, i));
449
+ ...f && a() ? { commit: () => {
450
+ f(), l.size && s(this, n, Atomics.load(t, i));
451
451
  } } : {},
452
452
  _version: {
453
453
  view: t,
@@ -455,7 +455,7 @@ var L = class {
455
455
  },
456
456
  _path: n
457
457
  });
458
- }), o() && (l(() => P), s({
458
+ }), a() && (c(() => P), o({
459
459
  type: "memory:bind",
460
460
  fields: this.entries.map((e, t) => [t, e.path]),
461
461
  totalBytes: this.totalBytes
@@ -506,10 +506,9 @@ function R(e, t = {}) {
506
506
  }
507
507
  function z(e) {
508
508
  for (let t of P) t.bind(e);
509
- m.info(`bound ${P.length} contract(s) — ${f(e.byteLength)} buffer`);
509
+ m.info(`bound ${P.length} contract(s) — ${u(e.byteLength)} buffer`);
510
510
  }
511
511
  function B() {
512
512
  return P.length;
513
513
  }
514
- //#endregion
515
514
  export { L as SharedMemory, z as bindSharedMemories, R as defineSharedMemory, k as field, B as getDefinedSharedMemoryCount, S as jsonCodec, w as registerConnectorFactory };
@@ -36,6 +36,23 @@ export interface MemoryPersistence {
36
36
  /** Final flush + release external resources. Invoked by pool.terminate(). */
37
37
  stop(): void | Promise<void>;
38
38
  }
39
+ /**
40
+ * A worker lifecycle transition, emitted by pools and dedicated workers
41
+ * through `onLifecycle`/`onWorkerEvent` — the seam error boundaries build
42
+ * on. `'error'` fires when a worker's error event lands (before respawn);
43
+ * `'respawn'` when the replacement is attached; `'terminate'` when the
44
+ * runner tears down deliberately.
45
+ */
46
+ export interface WorkerLifecycleEvent {
47
+ type: 'error' | 'respawn' | 'terminate';
48
+ /** The emitting runner's devtools correlation id ('worker-N'/'pool-N'). */
49
+ poolId: string;
50
+ /** Worker slot in a pool; always 0 for a dedicated worker. */
51
+ slot?: number;
52
+ /** The crash/error message on 'error' events. */
53
+ message?: string;
54
+ }
55
+ export type WorkerLifecycleListener = (event: WorkerLifecycleEvent) => void;
39
56
  export interface WorkerPoolConfig<S extends SharedSpec = SharedSpec, T extends TaskMap = TaskMap> {
40
57
  /** Worker entry as a URL — e.g. `new URL('./worker.ts', import.meta.url)`. */
41
58
  workerUrl?: URL;
@@ -80,6 +97,13 @@ export interface WorkerPoolConfig<S extends SharedSpec = SharedSpec, T extends T
80
97
  maxQueue?: number;
81
98
  /** Default true — a worker 'error' rejects its in-flight tasks and spawns a replacement. */
82
99
  respawn?: boolean;
100
+ /**
101
+ * Lifecycle observer — called on worker 'error' (before respawn),
102
+ * 'respawn', and 'terminate'. Island boundaries subscribe through
103
+ * `client.onWorkerEvent` to detect crashes; config-level listeners get
104
+ * the same events.
105
+ */
106
+ onLifecycle?: WorkerLifecycleListener;
83
107
  /**
84
108
  * Default per-task timeout in ms (per-call `options.timeout` overrides).
85
109
  * The timer starts at enqueue, so it bounds queue-wait + execution together.
@@ -1,4 +1,4 @@
1
- //#region src/contract/zod.ts
1
+ // src/contract/zod.ts
2
2
  var e = (e, t) => ({
3
3
  _zod: { def: e },
4
4
  evaluate: t
@@ -258,5 +258,4 @@ var te = {
258
258
  ZodArray: w,
259
259
  ZodString: y
260
260
  };
261
- //#endregion
262
261
  export { h as SchemaError, g as ZodType, $ as fluent, m as globalRegistry, te as z };
package/dist/devtools.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/devtools.ts
1
+ // src/devtools.ts
2
2
  var e = typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "worker" : "main", t = null, n = null, r = /* @__PURE__ */ new Set(), i = () => {
3
3
  if (r.size === 0) {
4
4
  t = n;
@@ -179,52 +179,45 @@ var e = typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "w
179
179
  let n = e.performance;
180
180
  if (!n) return;
181
181
  let r = n.memory, i = typeof WorkerGlobalScope < "u" && globalThis.self instanceof WorkerGlobalScope, a = n.measureUserAgentSpecificMemory?.bind(n), o = globalThis.process?.memoryUsage;
182
- if (r || a && !i || o) {
183
- if (E.add(e), a && !i) {
184
- setInterval(() => {
185
- a().then((e) => {
186
- let t = (e.breakdown ?? []).map((e) => ({
187
- bytes: e.bytes,
188
- scope: e.attribution?.[0]?.scope,
189
- url: e.attribution?.[0]?.url
190
- })).sort((e, t) => t.bytes - e.bytes).slice(0, 24);
191
- s({
192
- type: "runtime:memory",
193
- heapBytes: e.bytes,
194
- heapLimitBytes: r?.jsHeapSizeLimit,
195
- contexts: t
196
- });
197
- }).catch(() => {
198
- r && s({
199
- type: "runtime:memory",
200
- heapBytes: r.usedJSHeapSize,
201
- heapLimitBytes: r.jsHeapSizeLimit
202
- });
203
- });
204
- }, Math.max(t, 4e3)).unref?.();
205
- return;
206
- }
207
- setInterval(() => {
208
- if (r) s({
182
+ (r || a && !i || o) && (E.add(e), a && !i ? setInterval(() => {
183
+ a().then((e) => {
184
+ let t = (e.breakdown ?? []).map((e) => ({
185
+ bytes: e.bytes,
186
+ scope: e.attribution?.[0]?.scope,
187
+ url: e.attribution?.[0]?.url
188
+ })).sort((e, t) => t.bytes - e.bytes).slice(0, 24);
189
+ s({
190
+ type: "runtime:memory",
191
+ heapBytes: e.bytes,
192
+ heapLimitBytes: r?.jsHeapSizeLimit,
193
+ contexts: t
194
+ });
195
+ }).catch(() => {
196
+ r && s({
209
197
  type: "runtime:memory",
210
198
  heapBytes: r.usedJSHeapSize,
211
199
  heapLimitBytes: r.jsHeapSizeLimit
212
200
  });
213
- else if (o) {
214
- let e = o();
215
- s({
216
- type: "runtime:memory",
217
- heapBytes: e.heapUsed,
218
- rssBytes: e.rss
219
- });
220
- }
221
- }, t).unref?.();
222
- }
201
+ });
202
+ }, Math.max(t, 4e3)).unref?.() : setInterval(() => {
203
+ if (r) s({
204
+ type: "runtime:memory",
205
+ heapBytes: r.usedJSHeapSize,
206
+ heapLimitBytes: r.jsHeapSizeLimit
207
+ });
208
+ else if (o) {
209
+ let e = o();
210
+ s({
211
+ type: "runtime:memory",
212
+ heapBytes: e.heapUsed,
213
+ rssBytes: e.rss
214
+ });
215
+ }
216
+ }, t).unref?.());
223
217
  }, O = 0, k = /* @__PURE__ */ new Map(), A = (e, t) => {
224
218
  let n = t?.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
225
219
  if (!n) return `${e}-${++O}`;
226
220
  let r = `${n}-${e === "pool" ? "p" : e === "worker" ? "w" : e}`, i = (k.get(r) ?? 0) + 1;
227
221
  return k.set(r, i), i === 1 ? r : `${r}${i}`;
228
222
  };
229
- //#endregion
230
223
  export { o as addDevtoolsSink, l as devtoolsEnabled, s as emitDevtools, _ as enableWorkerDevtoolsForwarding, d as estimateCloneBytes, c as forwardDevtools, T as installFetchProbe, D as installMemoryProbe, m as listDevtoolsCommands, A as nextDevtoolsId, u as previewValue, p as registerDevtoolsCommand, h as runDevtoolsCommand, a as setDevtoolsSink };
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export type { Codec, Connector, ConnectorContext, ConnectorFactory, FieldDescrip
6
6
  export { msgpackrCodec } from './contract/msgpackrCodec.js';
7
7
  export { listSchema } from './contract/listSchema.js';
8
8
  export type { ListZodShape } from './contract/listSchema.js';
9
- export type { MemoryConfig, PoolTasks, Prettify, Schema, Logger, TaskContract, TaskMap, TaskMessage, TaskResult, MemoryPersistence, SharedWorkerConfig, ViewType, WorkerPoolConfig, } from './contract/types.js';
9
+ export type { MemoryConfig, PoolTasks, Prettify, Schema, Logger, TaskContract, TaskMap, TaskMessage, TaskResult, MemoryPersistence, SharedWorkerConfig, ViewType, WorkerLifecycleEvent, WorkerLifecycleListener, WorkerPoolConfig, } from './contract/types.js';
10
10
  export { MemoryManager } from './pool/memory.js';
11
11
  export { WorkerPool } from './pool/workerPool.js';
12
12
  export type { PoolStats, RunOptions } from './pool/workerPool.js';
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
- import { SchemaError as e, z as t } from "./contract/zod.js";
2
- import { listSchema as n } from "./contract/listSchema.js";
3
- import { addDevtoolsSink as r, devtoolsEnabled as i, emitDevtools as a, estimateCloneBytes as o, installFetchProbe as s, installMemoryProbe as c, listDevtoolsCommands as l, previewValue as u, registerDevtoolsCommand as d, runDevtoolsCommand as f, setDevtoolsSink as p } from "./devtools.js";
4
- import { msgpackrCodec as m } from "./contract/msgpackrCodec.js";
5
- import { reef as h } from "./contract/reef.js";
6
- import { getLogLevel as g, log as _, scoped as v, setLogLevel as y, setLogSink as b } from "./log.js";
7
- import { bindSharedMemories as x, defineSharedMemory as S, field as C, getDefinedSharedMemoryCount as w, jsonCodec as T, registerConnectorFactory as E } from "./contract/sharedMemory.js";
8
- import { MemoryManager as D } from "./pool/memory.js";
9
- import { PoolQueueFullError as O, TaskAbortedError as k, TaskTimeoutError as A, WorkerCrashedError as j } from "./pool/errors.js";
10
- import { WorkerPool as M } from "./pool/workerPool.js";
11
- import { DedicatedWorker as N } from "./pool/dedicatedWorker.js";
12
- import { connectWorker as P, resolveWorkerCount as F, workerClient as I } from "./pool/workerClient.js";
13
- import { connectSubWorker as L } from "./pool/subWorkerClient.js";
14
- import { connectSharedWorker as R } from "./shared/sharedWorkerClient.js";
15
- import { TaskRegistry as z } from "./worker/registry.js";
16
- import { sharedWorkerHost as B } from "./shared/sharedWorkerHost.js";
17
- import { createClient as V, defineService as H, implementService as U, rpc as W, serviceMethod as G } from "./service.js";
18
- import { RESERVED_CLIENT_KEYS as K, defineWorker as q } from "./worker/defineWorker.js";
19
- import { reactive as J, shallowEqual as Y, watch as X } from "./reactive.js";
20
- import { observe as Z } from "./observable.js";
21
- import { defineTask as Q, isAsyncTask as $, toTask as ee } from "./task.js";
22
- export { N as DedicatedWorker, D as MemoryManager, O as PoolQueueFullError, K as RESERVED_CLIENT_KEYS, e as SchemaError, k as TaskAbortedError, z as TaskRegistry, A as TaskTimeoutError, j as WorkerCrashedError, M as WorkerPool, r as addDevtoolsSink, x as bindSharedMemories, R as connectSharedWorker, L as connectSubWorker, P as connectWorker, V as createClient, H as defineService, S as defineSharedMemory, Q as defineTask, q as defineWorker, i as devtoolsEnabled, a as emitDevtools, o as estimateCloneBytes, C as field, w as getDefinedSharedMemoryCount, g as getLogLevel, U as implementService, s as installFetchProbe, c as installMemoryProbe, $ as isAsyncTask, T as jsonCodec, l as listDevtoolsCommands, n as listSchema, _ as log, m as msgpackrCodec, Z as observe, u as previewValue, J as reactive, h as reef, E as registerConnectorFactory, d as registerDevtoolsCommand, F as resolveWorkerCount, W as rpc, f as runDevtoolsCommand, v as scoped, G as serviceMethod, p as setDevtoolsSink, y as setLogLevel, b as setLogSink, Y as shallowEqual, B as sharedWorkerHost, ee as toTask, X as watch, I as workerClient, t as z };
1
+ import { bindSharedMemories as e, defineSharedMemory as t, field as n, getDefinedSharedMemoryCount as r, jsonCodec as i, registerConnectorFactory as a } from "./contract/sharedMemory.js";
2
+ import { reef as o } from "./contract/reef.js";
3
+ import { SchemaError as s, z as c } from "./contract/zod.js";
4
+ import { msgpackrCodec as l } from "./contract/msgpackrCodec.js";
5
+ import { listSchema as u } from "./contract/listSchema.js";
6
+ import { MemoryManager as d } from "./pool/memory.js";
7
+ import { WorkerPool as f } from "./pool/workerPool.js";
8
+ import { PoolQueueFullError as p, TaskAbortedError as m, TaskTimeoutError as h, WorkerCrashedError as g } from "./pool/errors.js";
9
+ import { DedicatedWorker as _ } from "./pool/dedicatedWorker.js";
10
+ import { connectWorker as v, resolveWorkerCount as y, workerClient as b } from "./pool/workerClient.js";
11
+ import { connectSubWorker as x } from "./pool/subWorkerClient.js";
12
+ import { connectSharedWorker as S } from "./shared/sharedWorkerClient.js";
13
+ import { sharedWorkerHost as C } from "./shared/sharedWorkerHost.js";
14
+ import { createClient as w, defineService as T, implementService as E, rpc as D, serviceMethod as O } from "./service.js";
15
+ import { TaskRegistry as k } from "./worker/registry.js";
16
+ import { RESERVED_CLIENT_KEYS as A, defineWorker as j } from "./worker/defineWorker.js";
17
+ import { reactive as M, shallowEqual as N, watch as P } from "./reactive.js";
18
+ import { observe as F } from "./observable.js";
19
+ import { defineTask as I, isAsyncTask as L, toTask as R } from "./task.js";
20
+ import { getLogLevel as z, log as B, scoped as V, setLogLevel as H, setLogSink as U } from "./log.js";
21
+ import { addDevtoolsSink as W, devtoolsEnabled as G, emitDevtools as K, estimateCloneBytes as q, installFetchProbe as J, installMemoryProbe as Y, listDevtoolsCommands as X, previewValue as Z, registerDevtoolsCommand as Q, runDevtoolsCommand as $, setDevtoolsSink as ee } from "./devtools.js";
22
+ export { _ as DedicatedWorker, d as MemoryManager, p as PoolQueueFullError, A as RESERVED_CLIENT_KEYS, s as SchemaError, m as TaskAbortedError, k as TaskRegistry, h as TaskTimeoutError, g as WorkerCrashedError, f as WorkerPool, W as addDevtoolsSink, e as bindSharedMemories, S as connectSharedWorker, x as connectSubWorker, v as connectWorker, w as createClient, T as defineService, t as defineSharedMemory, I as defineTask, j as defineWorker, G as devtoolsEnabled, K as emitDevtools, q as estimateCloneBytes, n as field, r as getDefinedSharedMemoryCount, z as getLogLevel, E as implementService, J as installFetchProbe, Y as installMemoryProbe, L as isAsyncTask, i as jsonCodec, X as listDevtoolsCommands, u as listSchema, B as log, l as msgpackrCodec, F as observe, Z as previewValue, M as reactive, o as reef, a as registerConnectorFactory, Q as registerDevtoolsCommand, y as resolveWorkerCount, D as rpc, $ as runDevtoolsCommand, V as scoped, O as serviceMethod, ee as setDevtoolsSink, H as setLogLevel, U as setLogSink, N as shallowEqual, C as sharedWorkerHost, R as toTask, P as watch, b as workerClient, c as z };
package/dist/log.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { devtoolsEnabled as e, emitDevtools as t, previewValue as n } from "./devtools.js";
2
- //#region src/log.ts
2
+ // src/log.ts
3
3
  var r = {
4
4
  trace: 0,
5
5
  debug: 1,
@@ -48,5 +48,4 @@ function p(e) {
48
48
  };
49
49
  }
50
50
  var m = (e) => e >= 1 << 20 ? `${(e / (1 << 20)).toFixed(1)}MB` : e >= 1024 ? `${(e / 1024).toFixed(1)}KB` : `${e}B`;
51
- //#endregion
52
51
  export { m as fmtBytes, l as getLogLevel, f as log, p as scoped, c as setLogLevel, u as setLogSink };
@@ -1,22 +1,22 @@
1
- import { scoped as e } from "./log.js";
1
+ import { watchNodes as e } from "./reactive.js";
2
2
  import { relabelNode as t } from "./reactiveGraph.js";
3
- import { watchNodes as n } from "./reactive.js";
4
- //#region src/observable.ts
5
- var r = e("observe");
6
- function i(e, i, a, o) {
3
+ import { scoped as n } from "./log.js";
4
+ // src/observable.ts
5
+ var r = n("observe");
6
+ function i(n, i, a, o) {
7
7
  let s = a ?? ((e) => e), c = o?.equals ?? Object.is, l, u = -1, d = null, f = null, p = null, m = null, h = null, g = /* @__PURE__ */ new Set(), _ = () => t(h, `observe(${String(i)}) · ${g.size} sub${g.size === 1 ? "" : "s"}`), v = () => {
8
8
  if (d || f) return;
9
9
  let t;
10
10
  try {
11
- t = e.connector(String(i));
11
+ t = n.connector(String(i));
12
12
  } catch {
13
- f = e.onBound(() => {
13
+ f = n.onBound(() => {
14
14
  let e = f;
15
15
  f = null, e?.(), v();
16
16
  });
17
17
  return;
18
18
  }
19
- let u = n(t, s, (e) => {
19
+ let u = e(t, s, (e) => {
20
20
  if (l === void 0 || !c(l, e)) {
21
21
  l = e;
22
22
  for (let t of g) t(e);
@@ -25,26 +25,26 @@ function i(e, i, a, o) {
25
25
  sliced: a !== void 0,
26
26
  label: "observe"
27
27
  });
28
- d = u.stop, h = u.effect, _(), m = t, p ??= e.onBound(() => {
29
- let t;
28
+ d = u.stop, h = u.effect, _(), m = t, p ??= n.onBound(() => {
29
+ let e;
30
30
  try {
31
- t = e.connector(String(i));
31
+ e = n.connector(String(i));
32
32
  } catch {
33
33
  return;
34
34
  }
35
- t !== m && (d?.(), d = null, m = null, v());
35
+ e !== m && (d?.(), d = null, m = null, v());
36
36
  }), r.debug(`observing "${String(i)}" (offset ${t.byteOffset})`);
37
37
  }, y = () => {
38
38
  d?.(), d = null, h = null, m = null, f?.(), f = null, p?.(), p = null;
39
39
  };
40
40
  return {
41
41
  get() {
42
- if (d || e.bound) try {
43
- let t = e.connector(String(i)), n = t._version ? Atomics.load(t._version.view, t._version.index) : 0;
44
- if (n !== u) {
45
- u = n;
46
- let e = s(t.read());
47
- (l === void 0 || !c(l, e)) && (l = e);
42
+ if (d || n.bound) try {
43
+ let e = n.connector(String(i)), t = e._version ? Atomics.load(e._version.view, e._version.index) : 0;
44
+ if (t !== u) {
45
+ u = t;
46
+ let n = s(e.read());
47
+ l !== void 0 && c(l, n) || (l = n);
48
48
  }
49
49
  } catch {}
50
50
  return l;
@@ -56,5 +56,4 @@ function i(e, i, a, o) {
56
56
  }
57
57
  };
58
58
  }
59
- //#endregion
60
59
  export { i as observe };
@@ -27,6 +27,7 @@ export declare class DedicatedWorker<S extends SharedSpec = SharedSpec> {
27
27
  private readonly mem;
28
28
  private readonly spawn;
29
29
  private readonly respawn;
30
+ private readonly onLifecycle?;
30
31
  private readonly taskTimeout?;
31
32
  private readonly label?;
32
33
  private worker;
@@ -43,6 +44,8 @@ export declare class DedicatedWorker<S extends SharedSpec = SharedSpec> {
43
44
  private attach;
44
45
  private detach;
45
46
  private handleReply;
47
+ /** Fan out a lifecycle transition — error boundaries subscribe through this. */
48
+ private lifecycle;
46
49
  private handleError;
47
50
  private rejectPending;
48
51
  /** Abort/timeout: the caller rejects now; the worker's eventual reply is discarded. */