@atolljs/core 0.1.2 → 0.1.4

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/dist/index11.js CHANGED
@@ -1,193 +1,52 @@
1
- import { fmtBytes as e, scoped as t } from "./index5.js";
2
- import { MemoryManager as n } from "./index9.js";
3
- import { PoolQueueFullError as r, TaskAbortedError as i, TaskTimeoutError as a, WorkerCrashedError as o } from "./index10.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);
11
- }
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);
1
+ import { WorkerPool as e } from "./index10.js";
2
+ //#region src/pool/workerClient.ts
3
+ var t = (e, n, r, i) => {
4
+ let a = /* @__PURE__ */ new Map();
5
+ return new Proxy(() => {}, {
6
+ get(o, s) {
7
+ if (s === "then" || typeof s == "symbol") return;
8
+ if (s === "with") return (i) => t(e, n, r, i);
9
+ if (e.length === 0 && r && s in r) return Reflect.get(r, s);
10
+ let c = a.get(s);
11
+ return c || (c = t([...e, s], n, r, i), a.set(s, c)), c;
12
+ },
13
+ apply(t, r, a) {
14
+ let o = n(), s = { taskId: e.join(".") };
15
+ return o.dispatch ? o.dispatch(s, a, i) : o.runTask(s, ...a);
49
16
  }
50
- Object.keys(a).length > 0 && s.info(`task methods: ${Object.keys(a).join(", ")}`);
51
- }
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;
65
- }
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();
188
- }
17
+ });
189
18
  };
19
+ function n(e) {
20
+ let n;
21
+ return t([], typeof e == "function" ? () => n ??= e() : () => e);
22
+ }
23
+ function r(n) {
24
+ let r = null, i = () => r ??= new e({
25
+ sharedMemory: n.sharedMemory,
26
+ createWorker: typeof n.worker == "function" ? n.worker : () => new Worker(n.worker, { type: "module" }),
27
+ poolSize: n.poolSize,
28
+ memory: n.memory,
29
+ concurrency: n.concurrency,
30
+ maxQueue: n.maxQueue,
31
+ respawn: n.respawn,
32
+ taskTimeout: n.taskTimeout
33
+ });
34
+ return n.lazy === !1 && i(), t([], i, {
35
+ start: () => {
36
+ i();
37
+ },
38
+ terminate: () => {
39
+ r?.terminate(), r = null;
40
+ },
41
+ get pool() {
42
+ return r;
43
+ },
44
+ get sharedMemory() {
45
+ return n.sharedMemory;
46
+ }
47
+ });
48
+ }
190
49
  //#endregion
191
- export { u as WorkerPool };
50
+ export { r as connectWorker, n as workerClient };
192
51
 
193
52
  //# sourceMappingURL=index11.js.map
package/dist/index12.js CHANGED
@@ -1,52 +1,66 @@
1
- import { WorkerPool as e } from "./index11.js";
2
- //#region src/pool/workerClient.ts
3
- var t = (e, n, r, i) => {
4
- let a = /* @__PURE__ */ new Map();
5
- return new Proxy(() => {}, {
6
- get(o, s) {
7
- if (s === "then" || typeof s == "symbol") return;
8
- if (s === "with") return (i) => t(e, n, r, i);
9
- if (e.length === 0 && r && s in r) return Reflect.get(r, s);
10
- let c = a.get(s);
11
- return c || (c = t([...e, s], n, r, i), a.set(s, c)), c;
12
- },
13
- apply(t, r, a) {
14
- let o = n(), s = { taskId: e.join(".") };
15
- return o.dispatch ? o.dispatch(s, a, i) : o.runTask(s, ...a);
1
+ import { scoped as e } from "./index5.js";
2
+ //#region src/shared/sharedWorkerClient.ts
3
+ var t = e("shared-client"), n = e("task"), r = class {
4
+ clientIndex;
5
+ sharedMemory;
6
+ port;
7
+ constructor(e, n, r) {
8
+ this.clientIndex = n, this.port = e, this.sharedMemory = r.sharedMemory;
9
+ let i = r.tasks ?? {};
10
+ for (let [e, n] of Object.entries(i)) {
11
+ if (e in this) {
12
+ t.warn(`task "${e}" collides with a SharedWorkerClient member — not installed`);
13
+ continue;
14
+ }
15
+ this[e] = (...e) => this.runTask(n, ...e);
16
16
  }
17
- });
18
- };
19
- function n(e) {
20
- let n;
21
- return t([], typeof e == "function" ? () => n ??= e() : () => e);
22
- }
23
- function r(n) {
24
- let r = null, i = () => r ??= new e({
25
- sharedMemory: n.sharedMemory,
26
- createWorker: typeof n.worker == "function" ? n.worker : () => new Worker(n.worker, { type: "module" }),
27
- poolSize: n.poolSize,
28
- memory: n.memory,
29
- concurrency: n.concurrency,
30
- maxQueue: n.maxQueue,
31
- respawn: n.respawn,
32
- taskTimeout: n.taskTimeout
33
- });
34
- return n.lazy === !1 && i(), t([], i, {
35
- start: () => {
36
- i();
37
- },
38
- terminate: () => {
39
- r?.terminate(), r = null;
40
- },
41
- get pool() {
42
- return r;
43
- },
44
- get sharedMemory() {
45
- return n.sharedMemory;
17
+ Object.keys(i).length > 0 && t.info(`task methods: ${Object.keys(i).join(", ")}`);
18
+ }
19
+ runTask(e, ...t) {
20
+ return new Promise((r, i) => {
21
+ let a = Math.random().toString(36).substring(2), o = performance.now();
22
+ n.debug(`→ ${e.taskId}`, { args: t });
23
+ let s = (t) => {
24
+ let c = t.data;
25
+ if (c.messageId === a) {
26
+ this.port.removeEventListener("message", s);
27
+ let t = (performance.now() - o).toFixed(1);
28
+ c.success ? (n.debug(`← ${e.taskId} ok`, { ms: +t }), r(c.result)) : (n.warn(`← ${e.taskId} failed: ${c.error}`, { ms: +t }), i(Error(c.error)));
29
+ }
30
+ };
31
+ this.port.addEventListener("message", s), this.port.postMessage({
32
+ type: "EXECUTE_TASK",
33
+ messageId: a,
34
+ taskId: e.taskId,
35
+ args: t
36
+ });
37
+ });
38
+ }
39
+ disconnect() {
40
+ try {
41
+ this.port.postMessage({ type: "SHARED_DISCONNECT" });
42
+ } finally {
43
+ this.port.close();
46
44
  }
45
+ }
46
+ };
47
+ async function i(e) {
48
+ if (typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated) throw Error("connectSharedWorker requires SharedArrayBuffer in a cross-origin isolated context — serve the page with COOP/COEP headers.");
49
+ if (!e.port && !e.workerUrl && !e.createWorker) throw Error("connectSharedWorker requires `workerUrl`, `createWorker`, or `port` in its config.");
50
+ let n = e.port ?? (e.createWorker ? e.createWorker().port : new SharedWorker(e.workerUrl, { type: "module" }).port);
51
+ return n.start(), await new Promise((i, a) => {
52
+ let o = setTimeout(() => a(/* @__PURE__ */ Error("connectSharedWorker: timed out waiting for the shared worker — is the host module calling sharedWorkerHost()?")), e.connectTimeoutMs ?? 1e4), s = (a) => {
53
+ let c = a.data;
54
+ c?.type === "SHARED_MEMORY" && (n.removeEventListener("message", s), clearTimeout(o), e.sharedMemory.bind(c.buffer), t.info(`connected as client #${c.clientIndex}`, { bytes: c.buffer.byteLength }), i(new r(n, c.clientIndex, e)));
55
+ };
56
+ n.addEventListener("message", s), n.postMessage({
57
+ type: "SHARED_CONNECT",
58
+ memoryBytes: e.sharedMemory.totalBytes,
59
+ memory: e.memory
60
+ });
47
61
  });
48
62
  }
49
63
  //#endregion
50
- export { r as connectWorker, n as workerClient };
64
+ export { i as connectSharedWorker };
51
65
 
52
66
  //# sourceMappingURL=index12.js.map
package/dist/index13.js CHANGED
@@ -1,66 +1,27 @@
1
1
  import { scoped as e } from "./index5.js";
2
- //#region src/shared/sharedWorkerClient.ts
3
- var t = e("shared-client"), n = e("task"), r = class {
4
- clientIndex;
5
- sharedMemory;
6
- port;
7
- constructor(e, n, r) {
8
- this.clientIndex = n, this.port = e, this.sharedMemory = r.sharedMemory;
9
- let i = r.tasks ?? {};
10
- for (let [e, n] of Object.entries(i)) {
11
- if (e in this) {
12
- t.warn(`task "${e}" collides with a SharedWorkerClient member — not installed`);
13
- continue;
14
- }
15
- this[e] = (...e) => this.runTask(n, ...e);
16
- }
17
- Object.keys(i).length > 0 && t.info(`task methods: ${Object.keys(i).join(", ")}`);
18
- }
19
- runTask(e, ...t) {
20
- return new Promise((r, i) => {
21
- let a = Math.random().toString(36).substring(2), o = performance.now();
22
- n.debug(`→ ${e.taskId}`, { args: t });
23
- let s = (t) => {
24
- let c = t.data;
25
- if (c.messageId === a) {
26
- this.port.removeEventListener("message", s);
27
- let t = (performance.now() - o).toFixed(1);
28
- c.success ? (n.debug(`← ${e.taskId} ok`, { ms: +t }), r(c.result)) : (n.warn(`← ${e.taskId} failed: ${c.error}`, { ms: +t }), i(Error(c.error)));
29
- }
30
- };
31
- this.port.addEventListener("message", s), this.port.postMessage({
32
- type: "EXECUTE_TASK",
33
- messageId: a,
34
- taskId: e.taskId,
35
- args: t
36
- });
2
+ //#region src/worker/registry.ts
3
+ var t = e("registry"), n = class {
4
+ static tasks = /* @__PURE__ */ new Map();
5
+ static register(e, n) {
6
+ this.tasks.set(e.taskId, {
7
+ contract: e,
8
+ handler: n
9
+ }), t.debug(`registered "${e.taskId}"`, {
10
+ args: e.argsSchema ? "validated" : "unvalidated",
11
+ result: e.resultSchema ? "validated" : "unvalidated"
37
12
  });
38
13
  }
39
- disconnect() {
40
- try {
41
- this.port.postMessage({ type: "SHARED_DISCONNECT" });
42
- } finally {
43
- this.port.close();
44
- }
14
+ static getContract(e) {
15
+ return this.tasks.get(e)?.contract;
16
+ }
17
+ static async execute(e, ...t) {
18
+ let n = this.tasks.get(e);
19
+ if (!n) throw Error(`Task handler not found for id: ${e}`);
20
+ let { contract: r, handler: i } = n, a = await i(...r.argsSchema ? r.argsSchema.parse(t) : t);
21
+ return r.resultSchema ? r.resultSchema.parse(a) : a;
45
22
  }
46
23
  };
47
- async function i(e) {
48
- if (typeof SharedArrayBuffer > "u" || typeof crossOriginIsolated < "u" && !crossOriginIsolated) throw Error("connectSharedWorker requires SharedArrayBuffer in a cross-origin isolated context — serve the page with COOP/COEP headers.");
49
- if (!e.port && !e.workerUrl && !e.createWorker) throw Error("connectSharedWorker requires `workerUrl`, `createWorker`, or `port` in its config.");
50
- let n = e.port ?? (e.createWorker ? e.createWorker().port : new SharedWorker(e.workerUrl, { type: "module" }).port);
51
- return n.start(), await new Promise((i, a) => {
52
- let o = setTimeout(() => a(/* @__PURE__ */ Error("connectSharedWorker: timed out waiting for the shared worker — is the host module calling sharedWorkerHost()?")), e.connectTimeoutMs ?? 1e4), s = (a) => {
53
- let c = a.data;
54
- c?.type === "SHARED_MEMORY" && (n.removeEventListener("message", s), clearTimeout(o), e.sharedMemory.bind(c.buffer), t.info(`connected as client #${c.clientIndex}`, { bytes: c.buffer.byteLength }), i(new r(n, c.clientIndex, e)));
55
- };
56
- n.addEventListener("message", s), n.postMessage({
57
- type: "SHARED_CONNECT",
58
- memoryBytes: e.sharedMemory.totalBytes,
59
- memory: e.memory
60
- });
61
- });
62
- }
63
24
  //#endregion
64
- export { i as connectSharedWorker };
25
+ export { n as TaskRegistry };
65
26
 
66
27
  //# sourceMappingURL=index13.js.map
package/dist/index14.js CHANGED
@@ -1,27 +1,63 @@
1
- import { scoped as e } from "./index5.js";
2
- //#region src/worker/registry.ts
3
- var t = e("registry"), n = class {
4
- static tasks = /* @__PURE__ */ new Map();
5
- static register(e, n) {
6
- this.tasks.set(e.taskId, {
7
- contract: e,
8
- handler: n
9
- }), t.debug(`registered "${e.taskId}"`, {
10
- args: e.argsSchema ? "validated" : "unvalidated",
11
- result: e.resultSchema ? "validated" : "unvalidated"
12
- });
13
- }
14
- static getContract(e) {
15
- return this.tasks.get(e)?.contract;
16
- }
17
- static async execute(e, ...t) {
18
- let n = this.tasks.get(e);
19
- if (!n) throw Error(`Task handler not found for id: ${e}`);
20
- let { contract: r, handler: i } = n, a = await i(...r.argsSchema ? r.argsSchema.parse(t) : t);
21
- return r.resultSchema ? r.resultSchema.parse(a) : a;
22
- }
23
- };
1
+ import { fmtBytes as e, scoped as t } from "./index5.js";
2
+ import { bindSharedMemories as n } from "./index6.js";
3
+ import { MemoryManager as r } from "./index8.js";
4
+ import { TaskRegistry as i } from "./index13.js";
5
+ //#region src/shared/sharedWorkerHost.ts
6
+ var a = t("shared-worker"), o = null, s = 0;
7
+ function c(t, i) {
8
+ if (o) return o.buffer.byteLength < t && a.warn(`client requested ${e(t)} but buffer is ${e(o.buffer.byteLength)} — first client's capacity wins`), o;
9
+ let s = new r(i);
10
+ return s.ensureCapacity(t), o = s.memory, n(s.getBuffer()), a.info(`shared buffer allocated (${e(o.buffer.byteLength)})`), o;
11
+ }
12
+ function l(e) {
13
+ let t = ++s;
14
+ a.info(`client #${t} connected`), e.onmessage = async (n) => {
15
+ let r = n.data;
16
+ if (r?.type === "SHARED_CONNECT") {
17
+ let n = c(r.memoryBytes ?? 0, r.memory);
18
+ e.postMessage({
19
+ type: "SHARED_MEMORY",
20
+ buffer: n.buffer,
21
+ clientIndex: t
22
+ });
23
+ return;
24
+ }
25
+ if (r?.type === "EXECUTE_TASK") {
26
+ let { messageId: n, taskId: s, args: c } = r;
27
+ if (!o) {
28
+ e.postMessage({
29
+ messageId: n,
30
+ success: !1,
31
+ error: "Shared memory not initialized in worker."
32
+ });
33
+ return;
34
+ }
35
+ let l = performance.now();
36
+ try {
37
+ let r = await i.execute(s, ...c || []);
38
+ a.debug(`task ${s} → ${(performance.now() - l).toFixed(1)}ms (client #${t})`), e.postMessage({
39
+ messageId: n,
40
+ success: !0,
41
+ result: r
42
+ });
43
+ } catch (t) {
44
+ a.warn(`task ${s} failed: ${t.message || String(t)}`), e.postMessage({
45
+ messageId: n,
46
+ success: !1,
47
+ error: t.message || String(t)
48
+ });
49
+ }
50
+ return;
51
+ }
52
+ r?.type === "SHARED_DISCONNECT" && (e.close(), a.info(`client #${t} disconnected`));
53
+ }, e.start();
54
+ }
55
+ function u() {
56
+ self.onconnect = (e) => {
57
+ l(e.ports[0]);
58
+ };
59
+ }
24
60
  //#endregion
25
- export { n as TaskRegistry };
61
+ export { l as attachSharedPort, u as sharedWorkerHost };
26
62
 
27
63
  //# sourceMappingURL=index14.js.map
package/dist/index15.js CHANGED
@@ -1,63 +1,50 @@
1
- import { fmtBytes as e, scoped as t } from "./index5.js";
2
- import { bindSharedMemories as n } from "./index6.js";
3
- import { MemoryManager as r } from "./index9.js";
4
- import { TaskRegistry as i } from "./index14.js";
5
- //#region src/shared/sharedWorkerHost.ts
6
- var a = t("shared-worker"), o = null, s = 0;
7
- function c(t, i) {
8
- if (o) return o.buffer.byteLength < t && a.warn(`client requested ${e(t)} but buffer is ${e(o.buffer.byteLength)} — first client's capacity wins`), o;
9
- let s = new r(i);
10
- return s.ensureCapacity(t), o = s.memory, n(s.getBuffer()), a.info(`shared buffer allocated (${e(o.buffer.byteLength)})`), o;
1
+ import { scoped as e } from "./index5.js";
2
+ import { TaskRegistry as t } from "./index13.js";
3
+ //#region src/service.ts
4
+ var n = e("service");
5
+ function r(e = {}) {
6
+ return e;
11
7
  }
12
- function l(e) {
13
- let t = ++s;
14
- a.info(`client #${t} connected`), e.onmessage = async (n) => {
15
- let r = n.data;
16
- if (r?.type === "SHARED_CONNECT") {
17
- let n = c(r.memoryBytes ?? 0, r.memory);
18
- e.postMessage({
19
- type: "SHARED_MEMORY",
20
- buffer: n.buffer,
21
- clientIndex: t
22
- });
23
- return;
24
- }
25
- if (r?.type === "EXECUTE_TASK") {
26
- let { messageId: n, taskId: s, args: c } = r;
27
- if (!o) {
28
- e.postMessage({
29
- messageId: n,
30
- success: !1,
31
- error: "Shared memory not initialized in worker."
32
- });
33
- return;
34
- }
35
- let l = performance.now();
36
- try {
37
- let r = await i.execute(s, ...c || []);
38
- a.debug(`task ${s} → ${(performance.now() - l).toFixed(1)}ms (client #${t})`), e.postMessage({
39
- messageId: n,
40
- success: !0,
41
- result: r
42
- });
43
- } catch (t) {
44
- a.warn(`task ${s} failed: ${t.message || String(t)}`), e.postMessage({
45
- messageId: n,
46
- success: !1,
47
- error: t.message || String(t)
48
- });
49
- }
50
- return;
51
- }
52
- r?.type === "SHARED_DISCONNECT" && (e.close(), a.info(`client #${t} disconnected`));
53
- }, e.start();
8
+ function i(e) {
9
+ return e;
54
10
  }
55
- function u() {
56
- self.onconnect = (e) => {
57
- l(e.ports[0]);
11
+ function a(e, t) {
12
+ let n = {};
13
+ for (let [r, i] of Object.entries(t)) {
14
+ let t = "def" in i ? i.def : i;
15
+ n[r] = {
16
+ taskId: t.taskId ?? `${e}.${r}`,
17
+ ...t.dataType ? { dataType: t.dataType } : {},
18
+ ...t.argsSchema ? { argsSchema: t.argsSchema } : {},
19
+ ...t.resultSchema ? { resultSchema: t.resultSchema } : {}
20
+ };
21
+ }
22
+ return {
23
+ name: e,
24
+ tasks: n
58
25
  };
59
26
  }
27
+ function o(e, r) {
28
+ let i = Object.keys(e.tasks).filter((e) => {
29
+ let t = r[e];
30
+ return typeof t != "function" && typeof t?.run != "function";
31
+ });
32
+ if (i.length > 0) throw Error(`implementService("${e.name}"): missing handlers for ${i.join(", ")}`);
33
+ for (let [n, i] of Object.entries(e.tasks)) {
34
+ let e = r[n];
35
+ t.register(i, typeof e == "function" ? e.bind(r) : e.run.bind(e));
36
+ }
37
+ return n.info(`service "${e.name}" implemented — ${Object.keys(e.tasks).join(", ")}`), {
38
+ service: e,
39
+ handlers: r
40
+ };
41
+ }
42
+ function s(e, t) {
43
+ let n = {};
44
+ for (let [r, i] of Object.entries(e.tasks)) n[r] = (...e) => t.runTask(i, ...e);
45
+ return n;
46
+ }
60
47
  //#endregion
61
- export { l as attachSharedPort, u as sharedWorkerHost };
48
+ export { s as createClient, a as defineService, o as implementService, r as rpc, i as serviceMethod };
62
49
 
63
50
  //# sourceMappingURL=index15.js.map