@offmain/workerkit 0.14.0 → 1.0.0
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/README.md +225 -46
- package/dist/define-worker.cjs +1 -0
- package/dist/define-worker.js +4 -0
- package/dist/index-2AONniOz.js +59 -0
- package/dist/index-CXKVsLvY.cjs +1 -0
- package/dist/index.cjs +195 -43
- package/dist/index.js +945 -487
- package/dist/types/tools/collect-results/collect-results.d.ts +26 -0
- package/dist/types/tools/collect-results/index.d.ts +2 -0
- package/dist/types/tools/collect-results/types.d.ts +10 -0
- package/dist/types/tools/define-worker/define-worker.d.ts +31 -0
- package/dist/types/tools/define-worker/define-worker.test.d.ts +1 -0
- package/dist/types/tools/define-worker/index.d.ts +1 -0
- package/dist/types/tools/define-worker-config/define-worker-config.d.ts +23 -0
- package/dist/types/tools/define-worker-config/index.d.ts +1 -0
- package/dist/types/tools/extract-transferable/extract-transferable.d.ts +15 -0
- package/dist/types/tools/extract-transferable/extract-transferable.test.d.ts +1 -0
- package/dist/types/tools/extract-transferable/index.d.ts +1 -0
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/logger/index.d.ts +2 -0
- package/dist/types/tools/logger/logger.d.ts +21 -0
- package/dist/types/tools/logger/logger.test.d.ts +1 -0
- package/dist/types/tools/logger/types.d.ts +6 -0
- package/dist/types/tools/main-worker-factory/main-worker-factory.d.ts +94 -228
- package/dist/types/tools/main-worker-factory/types.d.ts +71 -4
- package/dist/types/tools/memory-store/index.d.ts +3 -0
- package/dist/types/tools/memory-store/memory-store.d.ts +50 -0
- package/dist/types/tools/memory-store/memory-store.test.d.ts +1 -0
- package/dist/types/tools/memory-store/memory-worker-proxy.d.ts +75 -0
- package/dist/types/tools/memory-store/memory-worker.d.ts +11 -0
- package/dist/types/tools/orchestrator/index.d.ts +2 -0
- package/dist/types/tools/orchestrator/orchestrator.d.ts +21 -0
- package/dist/types/tools/orchestrator/orchestrator.test.d.ts +1 -0
- package/dist/types/tools/orchestrator/types.d.ts +10 -0
- package/dist/types/tools/partition-array/index.d.ts +1 -0
- package/dist/types/tools/partition-array/partition-array.d.ts +14 -0
- package/dist/types/tools/partition-array/partition-array.test.d.ts +1 -0
- package/dist/types/tools/persistent-manager/index.d.ts +2 -0
- package/dist/types/tools/persistent-manager/persistent-manager.d.ts +25 -0
- package/dist/types/tools/persistent-manager/persistent-manager.test.d.ts +1 -0
- package/dist/types/tools/persistent-manager/types.d.ts +9 -0
- package/dist/types/tools/pipeline/index.d.ts +2 -0
- package/dist/types/tools/pipeline/pipeline.d.ts +17 -0
- package/dist/types/tools/pipeline/pipeline.test.d.ts +1 -0
- package/dist/types/tools/pipeline/types.d.ts +13 -0
- package/dist/types/tools/run-worker/index.d.ts +2 -0
- package/dist/types/tools/run-worker/run-worker.d.ts +26 -0
- package/dist/types/tools/run-worker/run-worker.test.d.ts +1 -0
- package/dist/types/tools/run-worker/types.d.ts +14 -0
- package/dist/types/tools/worker-factory/index.d.ts +1 -1
- package/dist/types/tools/worker-factory/worker-factory.d.ts +7 -1
- package/dist/types/workers/initiator.d.ts +1 -1
- package/dist/types/workers/initiator.test.d.ts +1 -0
- package/package.json +11 -5
- package/dist/types/tools/define-worker.d.ts +0 -21
- /package/dist/types/tools/{define-worker.test.d.ts → collect-results/collect-results.test.d.ts} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var L=Object.defineProperty;var O=(o,e,r)=>e in o?L(o,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):o[e]=r;var y=(o,e,r)=>O(o,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("./index-CXKVsLvY.cjs"),D=`
|
|
2
2
|
const extractTransferables = (value, seen = new Set()) => {
|
|
3
3
|
if (value === null || typeof value !== 'object') return [];
|
|
4
4
|
if (seen.has(value)) return [];
|
|
@@ -12,31 +12,73 @@ const extractTransferables = (value, seen = new Set()) => {
|
|
|
12
12
|
if (Array.isArray(value)) return value.flatMap(i => extractTransferables(i, seen));
|
|
13
13
|
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
`,U=o=>`
|
|
16
|
+
${D}
|
|
16
17
|
self.addEventListener('message', async (event) => {
|
|
17
18
|
try {
|
|
18
|
-
const output = await ${
|
|
19
|
+
const output = await ${o}(event.data);
|
|
19
20
|
self.postMessage({ ok: true, data: output }, extractTransferables(output));
|
|
20
21
|
} catch (err) {
|
|
21
22
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
22
23
|
}
|
|
23
24
|
})
|
|
24
|
-
`,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
`,N=o=>`
|
|
26
|
+
${D}
|
|
27
|
+
const workerFn = ${o};
|
|
28
|
+
let memPort = null;
|
|
29
|
+
let factoryToken = null;
|
|
30
|
+
let pendingPayload = null;
|
|
31
|
+
|
|
32
|
+
async function runAndStore(payload) {
|
|
33
|
+
try {
|
|
34
|
+
const output = await workerFn(payload);
|
|
35
|
+
if (!memPort) {
|
|
36
|
+
// Fallback: no port provided, post data directly (legacy / opt-out path)
|
|
37
|
+
self.postMessage({ ok: true, data: output }, extractTransferables(output));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Store directly into MemoryWorker
|
|
41
|
+
const ref = 'mem_' + crypto.randomUUID();
|
|
42
|
+
await new Promise((resolve, reject) => {
|
|
43
|
+
memPort.onmessage = (e) => {
|
|
44
|
+
if (e.data && e.data.ref === ref) {
|
|
45
|
+
if (e.data.ok) resolve(e.data.ref);
|
|
46
|
+
else reject(new Error(e.data.error || 'MemoryWorker SET failed'));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
memPort.postMessage({ action: 'SET', factoryToken, ref, data: output });
|
|
50
|
+
});
|
|
51
|
+
// Only the token reaches the main thread
|
|
52
|
+
self.postMessage({ ok: true, __memory_ref__: ref });
|
|
53
|
+
} catch (err) {
|
|
54
|
+
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
33
55
|
}
|
|
34
|
-
|
|
35
|
-
if (Array.isArray(value)) return value.flatMap(i => extractTransferables(i, seen));
|
|
36
|
-
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
37
|
-
};
|
|
56
|
+
}
|
|
38
57
|
|
|
39
|
-
|
|
58
|
+
self.addEventListener('message', async (event) => {
|
|
59
|
+
// Init message: receive the MemoryWorker port and factory token
|
|
60
|
+
if (event.data && event.data.__init_memory_port__) {
|
|
61
|
+
memPort = event.ports[0] ?? event.data.memPort;
|
|
62
|
+
factoryToken = event.data.factoryToken;
|
|
63
|
+
if (memPort) memPort.start();
|
|
64
|
+
// If a payload arrived before the port, process it now
|
|
65
|
+
if (pendingPayload !== null) {
|
|
66
|
+
const p = pendingPayload;
|
|
67
|
+
pendingPayload = null;
|
|
68
|
+
await runAndStore(p);
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
// If port not yet received, queue the payload
|
|
73
|
+
if (!memPort) {
|
|
74
|
+
pendingPayload = event.data;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
await runAndStore(event.data);
|
|
78
|
+
});
|
|
79
|
+
`,j=o=>`
|
|
80
|
+
${D}
|
|
81
|
+
const workerFn = ${o};
|
|
40
82
|
let outputPort = null;
|
|
41
83
|
let inputPort = null;
|
|
42
84
|
let pendingData = null;
|
|
@@ -101,22 +143,9 @@ self.addEventListener('message', (event) => {
|
|
|
101
143
|
pendingData = event.data;
|
|
102
144
|
}
|
|
103
145
|
});
|
|
104
|
-
`,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (seen.has(value)) return [];
|
|
108
|
-
seen.add(value);
|
|
109
|
-
if (value instanceof ArrayBuffer || value instanceof MessagePort ||
|
|
110
|
-
(typeof ImageBitmap !== 'undefined' && value instanceof ImageBitmap) ||
|
|
111
|
-
(typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas)) {
|
|
112
|
-
return [value];
|
|
113
|
-
}
|
|
114
|
-
if (ArrayBuffer.isView(value)) return [value.buffer];
|
|
115
|
-
if (Array.isArray(value)) return value.flatMap(i => extractTransferables(i, seen));
|
|
116
|
-
return Object.values(value).flatMap(v => extractTransferables(v, seen));
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const workerFn = ${n};
|
|
146
|
+
`,G=o=>`
|
|
147
|
+
${D}
|
|
148
|
+
const workerFn = ${o};
|
|
120
149
|
let cachedDataset = null;
|
|
121
150
|
|
|
122
151
|
self.addEventListener('message', async (event) => {
|
|
@@ -157,14 +186,137 @@ self.addEventListener('message', async (event) => {
|
|
|
157
186
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
158
187
|
}
|
|
159
188
|
});
|
|
160
|
-
`;var
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
`;var S=(o=>(o.Default="default",o.Pipeline="pipeline",o.Persistent="persistent",o.Memory="memory",o))(S||{});const q=Object.freeze({persistent:G,pipeline:j,default:U,memory:N});class b{constructor(e,r){y(this,"_worker");if(r!=null&&r.createWorker)this._worker=r.createWorker();else if(e){const a=(r==null?void 0:r.mode)??"default",t=q[a](e.toString()),l=new Blob([t],{type:"application/javascript"});this._worker=new Worker(URL.createObjectURL(l))}else throw new Error("Either workerFunction or options.createWorker must be provided to WorkerFactory.")}get getWorker(){return this._worker}}class z{constructor(){y(this,"store",new Map)}register(e,r={}){this.store.set(e,r)}has(e){return this.store.has(e)}delete(e){return this.store.delete(e)}clear(){this.store.clear()}stats(){return{count:this.store.size,refs:Array.from(this.store.keys())}}}const K=`
|
|
190
|
+
const store = new Map();
|
|
191
|
+
|
|
192
|
+
function handleMessage(msg, replyTarget) {
|
|
193
|
+
if (!msg || typeof msg !== 'object') return;
|
|
194
|
+
|
|
195
|
+
const { action, factoryToken, expectedToken, ref, data, id } = msg;
|
|
196
|
+
|
|
197
|
+
// Initial handshake to set expected token if needed
|
|
198
|
+
if (action === 'INIT_TOKEN') {
|
|
199
|
+
self.__expectedToken = expectedToken;
|
|
200
|
+
replyTarget.postMessage({ ok: true, action: 'INIT_TOKEN_ACK' });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Validate factory token
|
|
205
|
+
if (self.__expectedToken && factoryToken !== self.__expectedToken) {
|
|
206
|
+
replyTarget.postMessage({ ok: false, error: 'Unauthorized: invalid factory token', id });
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
try {
|
|
211
|
+
switch (action) {
|
|
212
|
+
case 'SET': {
|
|
213
|
+
const refId = ref || ('mem_' + crypto.randomUUID());
|
|
214
|
+
store.set(refId, data);
|
|
215
|
+
replyTarget.postMessage({ ok: true, ref: refId, id });
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case 'GET': {
|
|
219
|
+
const resultData = store.get(ref);
|
|
220
|
+
const exists = store.has(ref);
|
|
221
|
+
replyTarget.postMessage({ ok: true, exists, data: resultData, ref, id });
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case 'DELETE': {
|
|
225
|
+
const deleted = store.delete(ref);
|
|
226
|
+
replyTarget.postMessage({ ok: true, deleted, ref, id });
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case 'CLEAR': {
|
|
230
|
+
store.clear();
|
|
231
|
+
replyTarget.postMessage({ ok: true, action: 'CLEAR_ACK', id });
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case 'STATS': {
|
|
235
|
+
replyTarget.postMessage({
|
|
236
|
+
ok: true,
|
|
237
|
+
stats: {
|
|
238
|
+
count: store.size,
|
|
239
|
+
refs: Array.from(store.keys()),
|
|
240
|
+
},
|
|
241
|
+
id,
|
|
169
242
|
});
|
|
170
|
-
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case 'REGISTER_PORT': {
|
|
246
|
+
// Register a MessagePort from a computing or reducer worker.
|
|
247
|
+
// All messages arriving on this port are handled with the same
|
|
248
|
+
// store operations, enabling direct worker-to-MemoryWorker data flow.
|
|
249
|
+
const port = msg.port;
|
|
250
|
+
if (!port) {
|
|
251
|
+
replyTarget.postMessage({ ok: false, error: 'REGISTER_PORT requires a port', id });
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
port.onmessage = (event) => handleMessage(event.data, port);
|
|
255
|
+
port.start();
|
|
256
|
+
replyTarget.postMessage({ ok: true, action: 'PORT_REGISTERED', id });
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
default:
|
|
260
|
+
replyTarget.postMessage({ ok: false, error: 'Unknown action: ' + action, id });
|
|
261
|
+
}
|
|
262
|
+
} catch (err) {
|
|
263
|
+
replyTarget.postMessage({
|
|
264
|
+
ok: false,
|
|
265
|
+
error: err instanceof Error ? err.message : String(err),
|
|
266
|
+
id,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
self.addEventListener('message', (event) => {
|
|
272
|
+
// Handle REGISTER_PORT specially — the port itself is a Transferable in event.ports
|
|
273
|
+
if (event.data && event.data.action === 'REGISTER_PORT') {
|
|
274
|
+
const port = event.ports[0] ?? event.data.port;
|
|
275
|
+
const msg = { ...event.data, port };
|
|
276
|
+
handleMessage(msg, self);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
handleMessage(event.data, self);
|
|
280
|
+
});
|
|
281
|
+
`;class H{constructor(e){y(this,"worker");y(this,"factoryToken");y(this,"pending",new Map);this.factoryToken=e;const r=new Blob([K],{type:"application/javascript"});this.worker=new Worker(URL.createObjectURL(r)),this.worker.onmessage=a=>{const{id:t}=a.data??{};if(t&&this.pending.has(t)){const l=this.pending.get(t);this.pending.delete(t),l(a.data)}},this.worker.postMessage({action:"INIT_TOKEN",expectedToken:e})}send(e,r={}){return new Promise(a=>{const t=`req_${crypto.randomUUID()}`;this.pending.set(t,a),this.worker.postMessage({action:e,factoryToken:this.factoryToken,id:t,...r})})}async set(e,r){const a=await this.send("SET",{data:e,ref:r});if(!a.ok)throw new Error(a.error);return a.ref}async get(e){const r=await this.send("GET",{ref:e});if(!r.ok)throw new Error(r.error);return r.data}async has(e){const r=await this.send("GET",{ref:e});if(!r.ok)throw new Error(r.error);return!!r.exists}async delete(e){const r=await this.send("DELETE",{ref:e});if(!r.ok)throw new Error(r.error);return!!r.deleted}async clear(){const e=await this.send("CLEAR");if(!e.ok)throw new Error(e.error)}async stats(){const e=await this.send("STATS");if(!e.ok)throw new Error(e.error);return e.stats}async allocateWorkerPort(){const e=new MessageChannel,{port1:r,port2:a}=e,t=`req_${crypto.randomUUID()}`;return this.pending.set(t,()=>{}),this.worker.postMessage({action:"REGISTER_PORT",factoryToken:this.factoryToken,id:t},[r]),await new Promise(l=>{const f=this.pending.get(t);this.pending.set(t,m=>{f(m),l()})}),a}terminate(){this.pending.clear(),this.worker.terminate()}}class J{constructor(e="error"){y(this,"level");this.level=e}setLevel(e){this.level=e}verbose(...e){this.level==="verbose"&&console.debug("[WorkerManager]",...e)}info(...e){(this.level==="verbose"||this.level==="info")&&console.info("[WorkerManager]",...e)}error(...e){this.level!=="silent"&&console.error("[WorkerManager]",...e)}}class V{constructor(e){this.results=e}}function x(o,e){if(!o.length)return[];if(e<=0)throw new Error("numChunks must be positive");const r=Math.min(e,o.length),a=Math.floor(o.length/r),t=o.length%r,l=[];let f=0;for(let m=0;m<r;m++){const i=a+(m<t?1:0);l.push(o.slice(f,f+i)),f+=i}return l}async function B(o,e={},r){if(r.isTerminated())throw r.logger.error("Attempted to collect results after MainWorkerFactory was terminated"),new Error("MainWorkerFactory has been terminated");const a=o.results.filter(n=>n.status==="fulfilled"),t=o.results.filter(n=>n.status==="rejected");if(a.length===0)return{data:[],succeeded:0,failed:t.length,errors:t};const l=a.map(n=>{var k;const c=(k=n.value.successResult)==null?void 0:k.data;return c==null?void 0:c.__memory_ref__}),f=l.every(n=>typeof n=="string"),m=e.reducer?e.reducer.toString():"(shards) => shards.flat()";let i;if(f&&typeof Worker<"u"&&typeof Blob<"u"&&typeof MessageChannel<"u"){const n=await r.memoryWorkerProxy.allocateWorkerPort(),c=`
|
|
282
|
+
const refs = ${JSON.stringify(l)};
|
|
283
|
+
const factoryToken = ${JSON.stringify(r.factoryToken)};
|
|
284
|
+
const reducer = ${m};
|
|
285
|
+
|
|
286
|
+
// collect-results.ts
|
|
287
|
+
|
|
288
|
+
self.addEventListener('message', async (event) => {
|
|
289
|
+
// event.ports[0] is the direct line to MemoryWorker
|
|
290
|
+
const memPort = event.ports[0];
|
|
291
|
+
if (!memPort) {
|
|
292
|
+
self.postMessage({ ok: false, error: 'No MemoryWorker port provided' });
|
|
293
|
+
self.close();
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
memPort.start();
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
// Fetch each shard directly from MemoryWorker
|
|
300
|
+
const shards = await Promise.all(refs.map((ref) =>
|
|
301
|
+
new Promise((resolve, reject) => {
|
|
302
|
+
const reqId = 'fetch_' + ref;
|
|
303
|
+
memPort.addEventListener('message', function handler(e) {
|
|
304
|
+
if (e.data && e.data.ref === ref) {
|
|
305
|
+
memPort.removeEventListener('message', handler);
|
|
306
|
+
if (e.data.ok) resolve(e.data.data);
|
|
307
|
+
else reject(new Error(e.data.error));
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
memPort.postMessage({ action: 'GET', factoryToken, ref, id: reqId });
|
|
311
|
+
})
|
|
312
|
+
));
|
|
313
|
+
|
|
314
|
+
const result = reducer(shards);
|
|
315
|
+
self.postMessage({ ok: true, data: result });
|
|
316
|
+
} catch (error) {
|
|
317
|
+
self.postMessage({ ok: false, error: String(error) });
|
|
318
|
+
} finally {
|
|
319
|
+
self.close();
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
`;try{i=await new Promise((k,d)=>{const p=new Blob([c],{type:"application/javascript"}),s=r.trackWorker(new Worker(URL.createObjectURL(p)));s.onmessage=u=>{r.terminateWorker(s),u.data.ok?k(u.data.data):(r.logger.error("Collect results reducer worker failed",u.data.error),d(new Error(u.data.error)))},s.onerror=u=>{r.terminateWorker(s),r.logger.error("Collect results reducer worker encountered an error event",u),d(u)},s.postMessage({__start__:!0},[n])})}catch{const k=await Promise.all(l.map(s=>r.memoryWorkerProxy.get(s))),d=s=>s.flat();i=(e.reducer??d)(k)}}else if(f){const n=await Promise.all(l.map(d=>r.memoryWorkerProxy.get(d))),c=d=>d.flat();i=(e.reducer??c)(n)}else{const n=a.map(d=>d.value.successResult.data),c=d=>d.flat();i=(e.reducer??c)(n)}return{data:i,succeeded:a.length,failed:t.length,errors:t}}async function X(o,e,r){var E,R;if(r.isTerminated())return r.logger.error("Attempted to execute worker after MainWorkerFactory was terminated"),Promise.reject(new Error("MainWorkerFactory has been terminated"));const a=r.findWorkerByName(o);if(!a)return r.logger.error(`Worker config not found for worker: "${o}"`),Promise.reject(new Error(`Worker "${o}" not found`));const{srcData:t,reducer:l,autoCollect:f=!0,...m}=e||{};let i=t;const n=m.__memory_ref__,c=!!m.deleteMemory;if(i===void 0&&n){if(!r.memoryStore.has(n))return r.logger.error(`Attempted to use invalid memory reference: "${n}"`),Promise.reject(new Error(`Memory reference "${n}" not found in MemoryStore`));i=await r.memoryWorkerProxy.get(n),delete m.__memory_ref__,delete m.deleteMemory}else delete m.deleteMemory;const k=a.maxConcurrency??r.threads,d=!!(Array.isArray(i)&&a.partition),p=d?x(i,k):i,s=d&&Array.isArray(p)?p.length:k,u=r.orchestrator.createWorkerPromises(a,o,{data:p,...m},s,d),h=await Promise.allSettled(u);c&&n&&(await r.memoryWorkerProxy.delete(n),r.memoryStore.delete(n));for(const g of h)if(g.status==="fulfilled"){const W=(E=g.value.successResult)==null?void 0:E.data,w=W==null?void 0:W.__memory_ref__;w&&r.memoryStore.register(w)}const _=new V(h);if(!f){const g=h.filter(w=>w.status==="fulfilled").length,W=h.filter(w=>w.status==="rejected");return{data:_,succeeded:g,failed:W.length,errors:W}}const T=await B(_,{reducer:l},{isTerminated:()=>r.isTerminated(),trackWorker:r.orchestrator.context?g=>g:g=>g,terminateWorker:g=>{},logger:r.logger,memoryWorkerProxy:r.memoryWorkerProxy,factoryToken:r.factoryToken}),M=!!(a.memory||a.memoryOnly);for(const g of h)if(g.status==="fulfilled"){const W=(R=g.value.successResult)==null?void 0:R.data,w=W==null?void 0:W.__memory_ref__;w&&(r.memoryStore.delete(w),await r.memoryWorkerProxy.delete(w))}if(M){const g=await r.memoryWorkerProxy.set(T.data);return r.memoryStore.register(g),{...T,__memory_ref__:g}}return T}async function Q(o,e){if(e.isTerminated())throw e.logger.error("Attempted to execute pipeline after MainWorkerFactory was terminated"),new Error("MainWorkerFactory has been terminated");if(o.length===0)throw e.logger.error("Attempted to execute an empty pipeline"),new Error("Pipeline requires at least one step");if(o.length===1){const r=o[0],{worker:a,srcData:t,...l}=r,f=e.findWorkerByName(r.worker);if(!f)throw e.logger.error(`Pipeline step config not found for worker: "${r.worker}"`),new Error(`Worker "${r.worker}" not found`);const m=new b(f.func,{createWorker:f.createWorker});e.trackWorker(m.getWorker);const i=m.getWorker;return new Promise((n,c)=>{i.onmessage=p=>{var s,u;e.terminateWorker(i),((s=p.data)==null?void 0:s.ok)===!1?(e.logger.error(`Pipeline step ${r.worker} failed`,p.data.error),c(new Error(p.data.error))):n({data:(u=p.data)==null?void 0:u.data,succeeded:1,failed:0,errors:[]})},i.onerror=p=>{e.terminateWorker(i),e.logger.error(`Pipeline step ${r.worker} encountered an error event`,p),c(p)};const d={data:t??{},...l,index:0};e.logger.verbose(`Starting single-step pipeline for worker ${r.worker}`),i.postMessage(d,v.extractTransferable(d))})}return new Promise(async(r,a)=>{const t=[],l=[];for(const s of o){const u=e.findWorkerByName(s.worker);if(!u){e.logger.error(`Pipeline step config not found for worker: "${s.worker}"`),a(new Error(`Worker "${s.worker}" not found`));return}const h=new b(u.func,{mode:S.Pipeline,createWorker:u.createWorker}),_=e.trackWorker(h.getWorker);t.push(_)}for(let s=0;s<t.length-1;s++)l.push(new MessageChannel);for(let s=0;s<t.length;s++){const{worker:u,srcData:h,..._}=o[s],T=[],M={};if(s>0&&(M.inputPort=l[s-1].port1,T.push(M.inputPort)),s<t.length-1&&(M.outputPort=l[s].port2,T.push(M.outputPort)),t[s].postMessage({__pipeline_ports__:!0,stepParams:_,...M},T),s<t.length-1){const E=t[s],R=t[s+1],{worker:g,srcData:W,...w}=o[s+1];E.onmessage=P=>{var F,I;if(P.data&&P.data.__pipeline_ports__)return;if(((F=P.data)==null?void 0:F.ok)===!1){e.logger.error(`Pipeline step ${o[s].worker} failed`,P.data.error),t.forEach(C=>e.terminateWorker(C)),a(new Error(P.data.error));return}const $={data:((I=P.data)==null?void 0:I.ok)!==void 0?P.data.data:P.data,...w,index:0};R.postMessage($,v.extractTransferable($))},E.onerror=P=>{e.logger.error(`Pipeline step ${o[s].worker} encountered an error event`,P),t.forEach(A=>e.terminateWorker(A)),a(P)}}}const f=t[t.length-1];f.onmessage=s=>{var u,h;t.forEach(_=>e.terminateWorker(_)),((u=s.data)==null?void 0:u.ok)===!1?(e.logger.error("Final pipeline step failed",s.data.error),a(new Error(s.data.error))):r({data:(h=s.data)==null?void 0:h.data,succeeded:1,failed:0,errors:[]})},f.onerror=s=>{t.forEach(u=>e.terminateWorker(u)),e.logger.error("Final pipeline step encountered an error event",s),a(s)};const{worker:m,srcData:i,...n}=o[0];let c=i;const k=n.__memory_ref__,d=!!n.deleteMemory;if(c===void 0&&k){if(!e.memoryStore.has(k)){t.forEach(s=>e.terminateWorker(s)),e.logger.error(`Memory reference "${k}" not found in MemoryStore`),a(new Error(`Memory reference "${k}" not found in MemoryStore`));return}c=await e.memoryWorkerProxy.get(k),d&&(e.memoryStore.delete(k),await e.memoryWorkerProxy.delete(k)),delete n.__memory_ref__,delete n.deleteMemory}c===void 0&&(c={});const p={data:c,...n,index:0};e.logger.verbose(`Starting full pipeline with ${o.length} steps`),t[0].postMessage(p,v.extractTransferable(p))})}class Y{constructor(e){y(this,"_persistentWorkers",new Map);this.context=e}async runPersistent(e,r){if(this.context.isTerminated())throw this.context.logger.error("Attempted to run persistent worker after MainWorkerFactory was terminated"),new Error("MainWorkerFactory has been terminated");const a=this.context.findWorkerByName(e);if(!a)throw this.context.logger.error(`Persistent worker config not found for worker: "${e}"`),new Error(`Worker "${e}" not found`);let t=this._persistentWorkers.get(e);if(!t){const l=new b(a.func,{mode:S.Persistent,createWorker:a.createWorker});t=this.context.trackWorker(l.getWorker),this.context.logger.verbose(`Created persistent worker for ${e}`),this._persistentWorkers.set(e,t)}return new Promise((l,f)=>{t.onmessage=i=>{var n,c;((n=i.data)==null?void 0:n.ok)===!1?(this.context.logger.error(`Persistent worker ${e} failed`,i.data.error),f(new Error(i.data.error))):l((c=i.data)==null?void 0:c.data)},t.onerror=i=>{this.context.logger.error(`Persistent worker ${e} encountered an error event`,i),f(i)};const m={type:"run",config:r.config};r.dataset!==void 0&&(m.dataset=r.dataset),t.postMessage(m,v.extractTransferable(m))})}release(e){const r=this._persistentWorkers.get(e);if(r){try{r.postMessage({type:"release"})}catch{}this.context.terminateWorker(r),this._persistentWorkers.delete(e)}}terminateAll(){for(const e of this._persistentWorkers.values()){try{e.postMessage({type:"release"})}catch{}this.context.terminateWorker(e)}this._persistentWorkers.clear()}}class Z{constructor(e){this.context=e}createWorkerPromises(e,r,a,t,l){const{data:f,...m}=a;return Array.from({length:t},(i,n)=>{const c=l&&Array.isArray(f)?f[n]:f;return this.runWorkerWithRetry({workerFunc:e.func,createWorker:e.createWorker,workerName:r,index:n,data:{data:c,...m}},e.retries)})}async runWorkerWithRetry(e,r=2){try{return await this.initiateWorker(e)}catch(a){if(r>0)return this.context.logger.info(`Worker ${e.index} failed, retrying (${r} left):`,a),this.runWorkerWithRetry(e,r-1);throw this.context.logger.error("Worker failed after all retries:",a),a}}async initiateWorker({workerFunc:e,createWorker:r,workerName:a,index:t,data:l}){const f=await this.context.memoryWorkerProxy.allocateWorkerPort();return new Promise((m,i)=>{if(this.context.isTerminated()){i(new Error("MainWorkerFactory has been terminated"));return}const n=new b(e,{createWorker:r,mode:S.Memory}),c=this.context.trackWorker(n.getWorker);c.onerror=d=>{this.context.terminateWorker(c),i({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:a,index:t,data:l},failedResult:d})},c.onmessage=d=>{var u,h,_;if(((u=d.data)==null?void 0:u.ok)===!1){this.context.terminateWorker(c),i({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:a,index:t,data:l},failedResult:new ErrorEvent("error",{message:d.data.error})});return}const p=(h=d.data)==null?void 0:h.__memory_ref__,s=p!==void 0?{__memory_ref__:p}:((_=d.data)==null?void 0:_.ok)!==void 0?d.data.data:d.data;m({index:t,workerConfigs:{workerFunc:e,createWorker:r,workerName:a,index:t,data:l},successResult:new MessageEvent("message",{data:s})}),this.context.terminateWorker(c)};const k={index:t,...Array.isArray(l)?{data:l}:l};c.postMessage({__init_memory_port__:!0,factoryToken:this.context.factoryToken},[f]),c.postMessage(k,v.extractTransferable(k))})}}class ee{constructor(e){y(this,"_workers");y(this,"_threads");y(this,"_activeWorkers",new Set);y(this,"_memoryStore",new z);y(this,"_memoryWorkerProxy");y(this,"_factoryToken");y(this,"_isTerminated",!1);y(this,"_persistentManager");y(this,"_orchestrator");y(this,"logger");this._workers=e.workers,this.logger=new J(e.logLevel??"error"),this._threads=typeof navigator<"u"&&navigator.hardwareConcurrency?navigator.hardwareConcurrency:4,this._factoryToken=crypto.randomUUID(),this._memoryWorkerProxy=new H(this._factoryToken);const r={isTerminated:()=>this.isTerminated,findWorkerByName:this.findWorkerByName.bind(this),trackWorker:this.trackWorker.bind(this),terminateWorker:this.terminateWorker.bind(this),logger:this.logger,memoryWorkerProxy:this._memoryWorkerProxy,factoryToken:this._factoryToken};this._persistentManager=new Y(r),this._orchestrator=new Z(r)}get isTerminated(){return this._isTerminated}trackWorker(e){if(this._isTerminated)throw e.terminate(),new Error("MainWorkerFactory has been terminated");return this._activeWorkers.add(e),e}terminateWorker(e){this._activeWorkers.delete(e);try{e.terminate()}catch{}}partitionArray(e,r){return x(e,r)}findWorkerByName(e){return this._workers.find(r=>r.name===e)}async runWorker(e,r){return X(e,r,{isTerminated:()=>this.isTerminated,findWorkerByName:this.findWorkerByName.bind(this),memoryStore:this._memoryStore,memoryWorkerProxy:this._memoryWorkerProxy,factoryToken:this._factoryToken,threads:this._threads,orchestrator:this._orchestrator,logger:this.logger})}async deleteMemory(e){return this._memoryStore.delete(e),this._memoryWorkerProxy.delete(e)}async clearMemory(){this._memoryStore.clear(),await this._memoryWorkerProxy.clear()}async getMemoryStats(){return this._memoryWorkerProxy.stats()}async collectResults(e,r={}){return B(e,r,{isTerminated:()=>this.isTerminated,trackWorker:this.trackWorker.bind(this),terminateWorker:this.terminateWorker.bind(this),logger:this.logger,memoryWorkerProxy:this._memoryWorkerProxy,factoryToken:this._factoryToken})}async pipeline(e){return Q(e,{memoryStore:this._memoryStore,memoryWorkerProxy:this._memoryWorkerProxy,isTerminated:()=>this.isTerminated,findWorkerByName:this.findWorkerByName.bind(this),trackWorker:this.trackWorker.bind(this),terminateWorker:this.terminateWorker.bind(this),logger:this.logger})}async runPersistent(e,r){return this._persistentManager.runPersistent(e,r)}release(e){this._persistentManager.release(e)}terminate(){this._isTerminated=!0,this._persistentManager.terminateAll();for(const e of Array.from(this._activeWorkers))this.terminateWorker(e);this._activeWorkers.clear(),this._memoryStore.clear(),this._memoryWorkerProxy.terminate()}destroy(){this.terminate()}reset(){this.terminate(),this._isTerminated=!1}restart(){this.reset()}}function re(o){return o===void 0?e=>e:o}function te(...o){return o}exports.defineWorker=v.defineWorker;exports.MainWorkerFactory=ee;exports.WorkerFactory=b;exports.WorkerMode=S;exports.defineWorkerConfig=re;exports.defineWorkerConfigs=te;
|