@offmain/workerkit 0.12.2 → 0.13.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 +21 -15
- package/dist/index.cjs +6 -6
- package/dist/index.js +196 -99
- package/dist/types/tools/main-worker-factory/main-worker-factory.d.ts +39 -6
- package/dist/types/tools/main-worker-factory/types.d.ts +8 -7
- package/dist/types/tools/worker-factory/worker-factory.d.ts +4 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -57,23 +57,23 @@ console.log(data); // [15]
|
|
|
57
57
|
|
|
58
58
|
## WorkerConfig Options
|
|
59
59
|
|
|
60
|
-
| Option | Type
|
|
61
|
-
| ---------------- |
|
|
62
|
-
| `name` | `string`
|
|
63
|
-
| `role` | `string`
|
|
64
|
-
| `func` | `Function`
|
|
65
|
-
| `
|
|
66
|
-
| `maxConcurrency` | `number`
|
|
67
|
-
| `retries` | `number`
|
|
68
|
-
| `partition` | `boolean`
|
|
60
|
+
| Option | Type | Default | Description |
|
|
61
|
+
| ---------------- | -------------- | ------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| `name` | `string` | — | Unique identifier used to call the worker |
|
|
63
|
+
| `role` | `string` | — | Logical grouping label |
|
|
64
|
+
| `func` | `Function` | — | The exported worker function to run (optional if `createWorker` is provided) |
|
|
65
|
+
| `createWorker` | `() => Worker` | — | Worker factory function `() => new Worker(new URL(...))` for Webpack 5 / Vite static analysis |
|
|
66
|
+
| `maxConcurrency` | `number` | `navigator.hardwareConcurrency` | Max parallel worker instances — defaults to the number of logical CPU cores reported by the browser |
|
|
67
|
+
| `retries` | `number` | `0` | How many times to retry a failed shard before marking it as rejected |
|
|
68
|
+
| `partition` | `boolean` | `false` | Split array input across multiple workers automatically |
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
## Module Bundler Integration (`
|
|
72
|
+
## Module Bundler Integration (`createWorker`)
|
|
73
73
|
|
|
74
74
|
When worker logic relies on external npm packages (such as Luxon, `date-fns`, `i18next`, or custom data transformation modules), dynamic inline stringification (`.toString()`) cannot access those closed-over imports.
|
|
75
75
|
|
|
76
|
-
Passing `
|
|
76
|
+
Passing `createWorker` enables modern module bundlers (Webpack 5, Vite, Rollup, Parcel) to analyze and bundle the worker file along with all of its dependencies into a dedicated ES module worker chunk.
|
|
77
77
|
|
|
78
78
|
### Dedicated Worker Script
|
|
79
79
|
|
|
@@ -98,7 +98,9 @@ self.addEventListener('message', (event) => {
|
|
|
98
98
|
});
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
###
|
|
101
|
+
### Webpack 5 & Vite Static Analysis (`createWorker`)
|
|
102
|
+
|
|
103
|
+
Webpack 5 and Vite look for literal `new Worker(new URL(..., import.meta.url))` calls inside consumer source files. By providing a `createWorker` factory function, bundlers statically detect and bundle the worker into a separate JS file, while allowing `MainWorkerFactory` to scale `maxConcurrency` across multiple threads:
|
|
102
104
|
|
|
103
105
|
```ts
|
|
104
106
|
import { MainWorkerFactory } from '@offmain/workerkit';
|
|
@@ -108,9 +110,13 @@ const factory = new MainWorkerFactory({
|
|
|
108
110
|
{
|
|
109
111
|
name: 'transformData',
|
|
110
112
|
role: 'compute',
|
|
111
|
-
// Webpack 5
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
// Webpack 5 and Vite statically analyze new Worker(new URL(..., import.meta.url))
|
|
114
|
+
// written inside this factory function and emit an individual bundled JS chunk.
|
|
115
|
+
createWorker: () =>
|
|
116
|
+
new Worker(new URL('./transform-data.worker.ts', import.meta.url), {
|
|
117
|
+
type: 'module',
|
|
118
|
+
}),
|
|
119
|
+
maxConcurrency: 4, // Spawns up to 4 parallel worker instances
|
|
114
120
|
},
|
|
115
121
|
] as const,
|
|
116
122
|
});
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var y=Object.defineProperty;var w=(n,e,r)=>e in n?y(n,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):n[e]=r;var h=(n,e,r)=>w(n,typeof e!="symbol"?e+"":e,r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=n=>`
|
|
2
2
|
const extractTransferables = (value, seen = new Set()) => {
|
|
3
3
|
if (value === null || typeof value !== 'object') return [];
|
|
4
4
|
if (seen.has(value)) return [];
|
|
@@ -21,7 +21,7 @@ self.addEventListener('message', async (event) => {
|
|
|
21
21
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
|
-
`,
|
|
24
|
+
`,W=n=>`
|
|
25
25
|
const extractTransferables = (value, seen = new Set()) => {
|
|
26
26
|
if (value === null || typeof value !== 'object') return [];
|
|
27
27
|
if (seen.has(value)) return [];
|
|
@@ -93,7 +93,7 @@ self.addEventListener('message', (event) => {
|
|
|
93
93
|
pendingData = event.data;
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
|
-
`,
|
|
96
|
+
`,M=n=>`
|
|
97
97
|
const extractTransferables = (value, seen = new Set()) => {
|
|
98
98
|
if (value === null || typeof value !== 'object') return [];
|
|
99
99
|
if (seen.has(value)) return [];
|
|
@@ -149,8 +149,8 @@ self.addEventListener('message', async (event) => {
|
|
|
149
149
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
150
150
|
}
|
|
151
151
|
});
|
|
152
|
-
`;var
|
|
153
|
-
const reducer = ${
|
|
152
|
+
`;var m=(n=>(n.Default="default",n.Pipeline="pipeline",n.Persistent="persistent",n))(m||{});const P=Object.freeze({persistent:M,pipeline:W,default:v});class g{constructor(e,r){h(this,"_worker");if(r!=null&&r.createWorker)this._worker=r.createWorker();else if(e){const o=(r==null?void 0:r.mode)??"default",a=P[o](e.toString()),i=new Blob([a],{type:"application/javascript"});this._worker=new Worker(URL.createObjectURL(i))}else throw new Error("Either workerFunction or options.createWorker must be provided to WorkerFactory.")}get getWorker(){return this._worker}}class b{constructor(e){this.results=e}}function k(n,e=new Set){return n===null||typeof n!="object"?[]:e.has(n)?[]:(e.add(n),n instanceof ArrayBuffer||n instanceof MessagePort||typeof ImageBitmap<"u"&&n instanceof ImageBitmap||typeof OffscreenCanvas<"u"&&n instanceof OffscreenCanvas?[n]:ArrayBuffer.isView(n)?[n.buffer]:Array.isArray(n)?n.flatMap(r=>k(r,e)):Object.values(n).flatMap(r=>k(r,e)))}class _{constructor(e){h(this,"_workers");h(this,"_threads");h(this,"_persistentWorkers",new Map);h(this,"_activeWorkers",new Set);h(this,"_isTerminated",!1);this._workers=e.workers,this._threads=navigator.hardwareConcurrency}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{}}initWorker(e){const r=new g(e.func,{createWorker:e.createWorker});return this.trackWorker(r.getWorker),r}partitionArray(e,r){if(!e.length)return[];if(r<=0)throw new Error("numChunks must be positive");const o=Math.min(r,e.length),a=Math.floor(e.length/o),i=e.length%o,c=[];let u=0;for(let t=0;t<o;t++){const s=a+(t<i?1:0);c.push(e.slice(u,u+s)),u+=s}return c}findWorkerByName(e){return this._workers.find(r=>r.name===e)}async runWorker(e,{srcData:r,...o}){if(this._isTerminated)return Promise.reject(new Error("MainWorkerFactory has been terminated"));const a=this.findWorkerByName(e);if(!a)return Promise.reject(new Error(`Worker "${e}" not found`));const i=a.maxConcurrency??this._threads,c=!!(Array.isArray(r)&&r.length>1&&a.partition),u=c?this.partitionArray(r,i):r,t=this.createWorkerPromises(a,e,{data:u,...o},i,c),s=await Promise.allSettled(t);return new b(s)}createWorkerPromises(e,r,o,a,i){const{data:c,...u}=o;return Array.from({length:a},(t,s)=>{const f=i&&Array.isArray(c)?c[s]:c;return this.runWorkerWithRetry({workerFunc:e.func,createWorker:e.createWorker,workerName:r,index:s,data:{data:f,...u}},e.retries)})}async runWorkerWithRetry(e,r=2){try{return await this.initiateWorker(e)}catch(o){if(r>0)return console.error(`Worker ${e.index} failed, retrying (${r} left):`,o),this.runWorkerWithRetry(e,r-1);throw console.error("Worker failed after all retries:",o),o}}initiateWorker({workerFunc:e,createWorker:r,workerName:o,index:a,data:i}){return new Promise((c,u)=>{const s=this.initWorker({name:o,role:"",func:e,createWorker:r}).getWorker;s.onerror=l=>{this.terminateWorker(s),u({index:a,workerConfigs:{workerFunc:e,createWorker:r,workerName:o,index:a,data:i},failedResult:l})},s.onmessage=l=>{var d,p;if(((d=l.data)==null?void 0:d.ok)===!1){this.terminateWorker(s),u({index:a,workerConfigs:{workerFunc:e,createWorker:r,workerName:o,index:a,data:i},failedResult:new ErrorEvent("error",{message:l.data.error})});return}c({index:a,workerConfigs:{workerFunc:e,createWorker:r,workerName:o,index:a,data:i},successResult:new MessageEvent("message",{data:(p=l.data)==null?void 0:p.data})}),this.terminateWorker(s)};const f={index:a,...Array.isArray(i)?{data:i}:i};s.postMessage(f,k(f))})}async collectResults(e,r={}){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");const o=e.results.filter(t=>t.status==="fulfilled"),a=e.results.filter(t=>t.status==="rejected"),i=o.map(t=>t.value.successResult.data),c=r.reducer?r.reducer.toString():"(shards) => shards.flat()";return{data:await new Promise((t,s)=>{const f=`
|
|
153
|
+
const reducer = ${c};
|
|
154
154
|
self.addEventListener('message', (event) => {
|
|
155
155
|
try {
|
|
156
156
|
const result = reducer(event.data);
|
|
@@ -159,4 +159,4 @@ self.addEventListener('message', async (event) => {
|
|
|
159
159
|
self.postMessage({ ok: false, error: String(err) });
|
|
160
160
|
}
|
|
161
161
|
});
|
|
162
|
-
`,
|
|
162
|
+
`,l=new Blob([f],{type:"application/javascript"}),d=this.trackWorker(new Worker(URL.createObjectURL(l)));d.onmessage=p=>{this.terminateWorker(d),p.data.ok?t(p.data.data):s(new Error(p.data.error))},d.onerror=p=>{this.terminateWorker(d),s(p)},d.postMessage(i)}),succeeded:o.length,failed:a.length,errors:a}}async pipeline(e){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");if(e.length===0)throw new Error("Pipeline requires at least one step");if(e.length===1){const r=e[0],o=this.findWorkerByName(r.worker);if(!o)throw new Error(`Worker "${r.worker}" not found`);const i=this.initWorker(o).getWorker;return new Promise((c,u)=>{i.onmessage=s=>{var f,l;this.terminateWorker(i),((f=s.data)==null?void 0:f.ok)===!1?u(new Error(s.data.error)):c((l=s.data)==null?void 0:l.data)},i.onerror=s=>{this.terminateWorker(i),u(s)};const t=r.srcData??{};i.postMessage({data:t,index:0},k(t))})}return new Promise((r,o)=>{const a=[],i=[];for(const t of e){const s=this.findWorkerByName(t.worker);if(!s){o(new Error(`Worker "${t.worker}" not found`));return}const f=new g(s.func,{mode:m.Pipeline,createWorker:s.createWorker}),l=this.trackWorker(f.getWorker);a.push(l)}for(let t=0;t<a.length-1;t++)i.push(new MessageChannel);for(let t=0;t<a.length;t++){const s=[],f={};t>0&&(f.inputPort=i[t-1].port1,s.push(f.inputPort)),t<a.length-1&&(f.outputPort=i[t].port2,s.push(f.outputPort)),a[t].postMessage({__pipeline_ports__:!0,...f},s)}const c=a[a.length-1];c.onmessage=t=>{var s,f;a.forEach(l=>this.terminateWorker(l)),((s=t.data)==null?void 0:s.ok)===!1?o(new Error(t.data.error)):r((f=t.data)==null?void 0:f.data)},c.onerror=t=>{a.forEach(s=>this.terminateWorker(s)),o(t)};const u=e[0].srcData??{};a[0].postMessage({data:u,index:0},k(u))})}async runPersistent(e,r){if(this._isTerminated)throw new Error("MainWorkerFactory has been terminated");const o=this.findWorkerByName(e);if(!o)throw new Error(`Worker "${e}" not found`);let a=this._persistentWorkers.get(e);if(!a){const i=new g(o.func,{mode:m.Persistent,createWorker:o.createWorker});a=this.trackWorker(i.getWorker),this._persistentWorkers.set(e,a)}return new Promise((i,c)=>{a.onmessage=t=>{var s,f;((s=t.data)==null?void 0:s.ok)===!1?c(new Error(t.data.error)):i((f=t.data)==null?void 0:f.data)},a.onerror=t=>{c(t)};const u={type:"run",config:r.config};r.dataset!==void 0&&(u.dataset=r.dataset),a.postMessage(u,k(u))})}release(e){const r=this._persistentWorkers.get(e);if(r){try{r.postMessage({type:"release"})}catch{}this.terminateWorker(r),this._persistentWorkers.delete(e)}}terminate(){this._isTerminated=!0;for(const e of this._persistentWorkers.values()){try{e.postMessage({type:"release"})}catch{}this.terminateWorker(e)}this._persistentWorkers.clear();for(const e of Array.from(this._activeWorkers))this.terminateWorker(e);this._activeWorkers.clear()}destroy(){this.terminate()}reset(){this.terminate(),this._isTerminated=!1}restart(){this.reset()}}exports.MainWorkerFactory=_;exports.WorkerFactory=g;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var h = (n, e, r) =>
|
|
1
|
+
var w = Object.defineProperty;
|
|
2
|
+
var v = (n, e, r) => e in n ? w(n, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : n[e] = r;
|
|
3
|
+
var h = (n, e, r) => v(n, typeof e != "symbol" ? e + "" : e, r);
|
|
4
4
|
const y = (n) => `
|
|
5
5
|
const extractTransferables = (value, seen = new Set()) => {
|
|
6
6
|
if (value === null || typeof value !== 'object') return [];
|
|
@@ -24,7 +24,7 @@ self.addEventListener('message', async (event) => {
|
|
|
24
24
|
self.postMessage({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
25
25
|
}
|
|
26
26
|
})
|
|
27
|
-
`,
|
|
27
|
+
`, W = (n) => `
|
|
28
28
|
const extractTransferables = (value, seen = new Set()) => {
|
|
29
29
|
if (value === null || typeof value !== 'object') return [];
|
|
30
30
|
if (seen.has(value)) return [];
|
|
@@ -96,7 +96,7 @@ self.addEventListener('message', (event) => {
|
|
|
96
96
|
pendingData = event.data;
|
|
97
97
|
}
|
|
98
98
|
});
|
|
99
|
-
`,
|
|
99
|
+
`, M = (n) => `
|
|
100
100
|
const extractTransferables = (value, seen = new Set()) => {
|
|
101
101
|
if (value === null || typeof value !== 'object') return [];
|
|
102
102
|
if (seen.has(value)) return [];
|
|
@@ -153,37 +153,33 @@ self.addEventListener('message', async (event) => {
|
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
`;
|
|
156
|
-
var
|
|
157
|
-
const
|
|
158
|
-
persistent:
|
|
159
|
-
pipeline:
|
|
156
|
+
var m = /* @__PURE__ */ ((n) => (n.Default = "default", n.Pipeline = "pipeline", n.Persistent = "persistent", n))(m || {});
|
|
157
|
+
const P = Object.freeze({
|
|
158
|
+
persistent: M,
|
|
159
|
+
pipeline: W,
|
|
160
160
|
default: y
|
|
161
161
|
});
|
|
162
|
-
class
|
|
162
|
+
class g {
|
|
163
163
|
/**
|
|
164
|
-
* Creates a new `Worker` from the given function.
|
|
165
|
-
*
|
|
166
|
-
* The function is stringified, embedded into a self-contained worker script,
|
|
167
|
-
* converted to a `Blob` URL, and passed to the `Worker` constructor.
|
|
164
|
+
* Creates a new `Worker` from the given function or factory option.
|
|
168
165
|
*
|
|
169
166
|
* @param workerFunction - The function to run inside the worker thread.
|
|
170
167
|
* Must be self-contained — it cannot reference variables from the outer
|
|
171
168
|
* scope because it is serialized via `.toString()`.
|
|
172
|
-
* @param options - Optional configuration
|
|
173
|
-
* worker execution mode (default, pipeline, or persistent).
|
|
169
|
+
* @param options - Optional configuration containing `createWorker` or `mode`.
|
|
174
170
|
*/
|
|
175
171
|
constructor(e, r) {
|
|
176
172
|
h(this, "_worker");
|
|
177
|
-
if (r != null && r.
|
|
178
|
-
this._worker =
|
|
173
|
+
if (r != null && r.createWorker)
|
|
174
|
+
this._worker = r.createWorker();
|
|
179
175
|
else if (e) {
|
|
180
|
-
const o = (r == null ? void 0 : r.mode) ?? "default", a =
|
|
176
|
+
const o = (r == null ? void 0 : r.mode) ?? "default", a = P[o](e.toString()), i = new Blob([a], {
|
|
181
177
|
type: "application/javascript"
|
|
182
178
|
});
|
|
183
179
|
this._worker = new Worker(URL.createObjectURL(i));
|
|
184
180
|
} else
|
|
185
181
|
throw new Error(
|
|
186
|
-
"Either workerFunction or options.
|
|
182
|
+
"Either workerFunction or options.createWorker must be provided to WorkerFactory."
|
|
187
183
|
);
|
|
188
184
|
}
|
|
189
185
|
/**
|
|
@@ -201,12 +197,12 @@ class b {
|
|
|
201
197
|
this.results = e;
|
|
202
198
|
}
|
|
203
199
|
}
|
|
204
|
-
function
|
|
205
|
-
return n === null || typeof n != "object" ? [] : e.has(n) ? [] : (e.add(n), n instanceof ArrayBuffer || n instanceof MessagePort || typeof ImageBitmap < "u" && n instanceof ImageBitmap || typeof OffscreenCanvas < "u" && n instanceof OffscreenCanvas ? [n] : ArrayBuffer.isView(n) ? [n.buffer] : Array.isArray(n) ? n.flatMap((r) =>
|
|
206
|
-
(r) =>
|
|
200
|
+
function k(n, e = /* @__PURE__ */ new Set()) {
|
|
201
|
+
return n === null || typeof n != "object" ? [] : e.has(n) ? [] : (e.add(n), n instanceof ArrayBuffer || n instanceof MessagePort || typeof ImageBitmap < "u" && n instanceof ImageBitmap || typeof OffscreenCanvas < "u" && n instanceof OffscreenCanvas ? [n] : ArrayBuffer.isView(n) ? [n.buffer] : Array.isArray(n) ? n.flatMap((r) => k(r, e)) : Object.values(n).flatMap(
|
|
202
|
+
(r) => k(r, e)
|
|
207
203
|
));
|
|
208
204
|
}
|
|
209
|
-
class
|
|
205
|
+
class E {
|
|
210
206
|
/**
|
|
211
207
|
* Creates a new `MainWorkerFactory`.
|
|
212
208
|
*
|
|
@@ -216,18 +212,45 @@ class A {
|
|
|
216
212
|
h(this, "_workers");
|
|
217
213
|
h(this, "_threads");
|
|
218
214
|
h(this, "_persistentWorkers", /* @__PURE__ */ new Map());
|
|
215
|
+
h(this, "_activeWorkers", /* @__PURE__ */ new Set());
|
|
216
|
+
h(this, "_isTerminated", !1);
|
|
219
217
|
this._workers = e.workers, this._threads = navigator.hardwareConcurrency;
|
|
220
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Returns `true` if the factory has been terminated.
|
|
221
|
+
*/
|
|
222
|
+
get isTerminated() {
|
|
223
|
+
return this._isTerminated;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Registers an active worker instance for lifecycle tracking.
|
|
227
|
+
*/
|
|
228
|
+
trackWorker(e) {
|
|
229
|
+
if (this._isTerminated)
|
|
230
|
+
throw e.terminate(), new Error("MainWorkerFactory has been terminated");
|
|
231
|
+
return this._activeWorkers.add(e), e;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Terminates a worker instance and removes it from tracking.
|
|
235
|
+
*/
|
|
236
|
+
terminateWorker(e) {
|
|
237
|
+
this._activeWorkers.delete(e);
|
|
238
|
+
try {
|
|
239
|
+
e.terminate();
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
221
243
|
/**
|
|
222
244
|
* Instantiates a {@link WorkerFactory} for the given worker configuration.
|
|
223
245
|
*
|
|
224
|
-
* @param config - The worker configuration containing `func` or `
|
|
246
|
+
* @param config - The worker configuration containing `func` or `createWorker`.
|
|
225
247
|
* @returns A new `WorkerFactory` wrapping the worker.
|
|
226
248
|
*/
|
|
227
249
|
initWorker(e) {
|
|
228
|
-
|
|
229
|
-
|
|
250
|
+
const r = new g(e.func, {
|
|
251
|
+
createWorker: e.createWorker
|
|
230
252
|
});
|
|
253
|
+
return this.trackWorker(r.getWorker), r;
|
|
231
254
|
}
|
|
232
255
|
/**
|
|
233
256
|
* Splits an array into up to `numChunks` evenly-sized sub-arrays.
|
|
@@ -248,13 +271,13 @@ class A {
|
|
|
248
271
|
partitionArray(e, r) {
|
|
249
272
|
if (!e.length) return [];
|
|
250
273
|
if (r <= 0) throw new Error("numChunks must be positive");
|
|
251
|
-
const o = Math.min(r, e.length), a = Math.floor(e.length / o), i = e.length % o,
|
|
252
|
-
let
|
|
274
|
+
const o = Math.min(r, e.length), a = Math.floor(e.length / o), i = e.length % o, c = [];
|
|
275
|
+
let u = 0;
|
|
253
276
|
for (let t = 0; t < o; t++) {
|
|
254
277
|
const s = a + (t < i ? 1 : 0);
|
|
255
|
-
|
|
278
|
+
c.push(e.slice(u, u + s)), u += s;
|
|
256
279
|
}
|
|
257
|
-
return
|
|
280
|
+
return c;
|
|
258
281
|
}
|
|
259
282
|
/**
|
|
260
283
|
* Looks up a registered worker configuration by name.
|
|
@@ -295,15 +318,17 @@ class A {
|
|
|
295
318
|
srcData: r,
|
|
296
319
|
...o
|
|
297
320
|
}) {
|
|
321
|
+
if (this._isTerminated)
|
|
322
|
+
return Promise.reject(new Error("MainWorkerFactory has been terminated"));
|
|
298
323
|
const a = this.findWorkerByName(e);
|
|
299
324
|
if (!a)
|
|
300
325
|
return Promise.reject(new Error(`Worker "${e}" not found`));
|
|
301
|
-
const i = a.maxConcurrency ?? this._threads,
|
|
326
|
+
const i = a.maxConcurrency ?? this._threads, c = !!(Array.isArray(r) && r.length > 1 && a.partition), u = c ? this.partitionArray(r, i) : r, t = this.createWorkerPromises(
|
|
302
327
|
a,
|
|
303
328
|
e,
|
|
304
|
-
{ data:
|
|
329
|
+
{ data: u, ...o },
|
|
305
330
|
i,
|
|
306
|
-
|
|
331
|
+
c
|
|
307
332
|
), s = await Promise.allSettled(t);
|
|
308
333
|
return new b(s);
|
|
309
334
|
}
|
|
@@ -322,16 +347,16 @@ class A {
|
|
|
322
347
|
* @returns An array of promises, one per thread.
|
|
323
348
|
*/
|
|
324
349
|
createWorkerPromises(e, r, o, a, i) {
|
|
325
|
-
const { data:
|
|
350
|
+
const { data: c, ...u } = o;
|
|
326
351
|
return Array.from({ length: a }, (t, s) => {
|
|
327
|
-
const
|
|
352
|
+
const f = i && Array.isArray(c) ? c[s] : c;
|
|
328
353
|
return this.runWorkerWithRetry(
|
|
329
354
|
{
|
|
330
355
|
workerFunc: e.func,
|
|
331
|
-
|
|
356
|
+
createWorker: e.createWorker,
|
|
332
357
|
workerName: r,
|
|
333
358
|
index: s,
|
|
334
|
-
data: { data:
|
|
359
|
+
data: { data: f, ...u }
|
|
335
360
|
},
|
|
336
361
|
e.retries
|
|
337
362
|
);
|
|
@@ -373,57 +398,74 @@ class A {
|
|
|
373
398
|
* Any transferable objects found in the payload are moved (not copied) to
|
|
374
399
|
* the worker via the `transfer` list of `postMessage`.
|
|
375
400
|
*
|
|
376
|
-
* The underlying `Worker` is always terminated after the
|
|
377
|
-
* whether it succeeded or failed.
|
|
401
|
+
* The underlying `Worker` is always terminated after the message completes.
|
|
378
402
|
*
|
|
379
|
-
* @param instanceConfig - Worker function,
|
|
403
|
+
* @param instanceConfig - Worker function, factory, name, shard index, and data.
|
|
380
404
|
* @returns A promise that resolves with the worker's result.
|
|
381
405
|
*/
|
|
382
406
|
initiateWorker({
|
|
383
407
|
workerFunc: e,
|
|
384
|
-
|
|
408
|
+
createWorker: r,
|
|
385
409
|
workerName: o,
|
|
386
410
|
index: a,
|
|
387
411
|
data: i
|
|
388
412
|
}) {
|
|
389
|
-
return new Promise((
|
|
413
|
+
return new Promise((c, u) => {
|
|
390
414
|
const s = this.initWorker({
|
|
391
415
|
name: o,
|
|
392
416
|
role: "",
|
|
393
417
|
func: e,
|
|
394
|
-
|
|
418
|
+
createWorker: r
|
|
395
419
|
}).getWorker;
|
|
396
|
-
s.onerror = (
|
|
397
|
-
|
|
420
|
+
s.onerror = (l) => {
|
|
421
|
+
this.terminateWorker(s), u({
|
|
398
422
|
index: a,
|
|
399
|
-
workerConfigs: {
|
|
400
|
-
|
|
423
|
+
workerConfigs: {
|
|
424
|
+
workerFunc: e,
|
|
425
|
+
createWorker: r,
|
|
426
|
+
workerName: o,
|
|
427
|
+
index: a,
|
|
428
|
+
data: i
|
|
429
|
+
},
|
|
430
|
+
failedResult: l
|
|
401
431
|
});
|
|
402
|
-
}, s.onmessage = (
|
|
432
|
+
}, s.onmessage = (l) => {
|
|
403
433
|
var d, p;
|
|
404
|
-
if (((d =
|
|
405
|
-
|
|
434
|
+
if (((d = l.data) == null ? void 0 : d.ok) === !1) {
|
|
435
|
+
this.terminateWorker(s), u({
|
|
406
436
|
index: a,
|
|
407
|
-
workerConfigs: {
|
|
437
|
+
workerConfigs: {
|
|
438
|
+
workerFunc: e,
|
|
439
|
+
createWorker: r,
|
|
440
|
+
workerName: o,
|
|
441
|
+
index: a,
|
|
442
|
+
data: i
|
|
443
|
+
},
|
|
408
444
|
failedResult: new ErrorEvent("error", {
|
|
409
|
-
message:
|
|
445
|
+
message: l.data.error
|
|
410
446
|
})
|
|
411
447
|
});
|
|
412
448
|
return;
|
|
413
449
|
}
|
|
414
|
-
|
|
450
|
+
c({
|
|
415
451
|
index: a,
|
|
416
|
-
workerConfigs: {
|
|
452
|
+
workerConfigs: {
|
|
453
|
+
workerFunc: e,
|
|
454
|
+
createWorker: r,
|
|
455
|
+
workerName: o,
|
|
456
|
+
index: a,
|
|
457
|
+
data: i
|
|
458
|
+
},
|
|
417
459
|
successResult: new MessageEvent("message", {
|
|
418
|
-
data: (p =
|
|
460
|
+
data: (p = l.data) == null ? void 0 : p.data
|
|
419
461
|
})
|
|
420
|
-
}),
|
|
462
|
+
}), this.terminateWorker(s);
|
|
421
463
|
};
|
|
422
|
-
const
|
|
464
|
+
const f = {
|
|
423
465
|
index: a,
|
|
424
466
|
...Array.isArray(i) ? { data: i } : i
|
|
425
467
|
};
|
|
426
|
-
s.postMessage(
|
|
468
|
+
s.postMessage(f, k(f));
|
|
427
469
|
});
|
|
428
470
|
}
|
|
429
471
|
/**
|
|
@@ -459,15 +501,17 @@ class A {
|
|
|
459
501
|
* });
|
|
460
502
|
*/
|
|
461
503
|
async collectResults(e, r = {}) {
|
|
504
|
+
if (this._isTerminated)
|
|
505
|
+
throw new Error("MainWorkerFactory has been terminated");
|
|
462
506
|
const o = e.results.filter(
|
|
463
507
|
(t) => t.status === "fulfilled"
|
|
464
508
|
), a = e.results.filter(
|
|
465
509
|
(t) => t.status === "rejected"
|
|
466
|
-
), i = o.map((t) => t.value.successResult.data),
|
|
510
|
+
), i = o.map((t) => t.value.successResult.data), c = r.reducer ? r.reducer.toString() : "(shards) => shards.flat()";
|
|
467
511
|
return {
|
|
468
512
|
data: await new Promise((t, s) => {
|
|
469
|
-
const
|
|
470
|
-
const reducer = ${
|
|
513
|
+
const f = `
|
|
514
|
+
const reducer = ${c};
|
|
471
515
|
self.addEventListener('message', (event) => {
|
|
472
516
|
try {
|
|
473
517
|
const result = reducer(event.data);
|
|
@@ -476,11 +520,11 @@ class A {
|
|
|
476
520
|
self.postMessage({ ok: false, error: String(err) });
|
|
477
521
|
}
|
|
478
522
|
});
|
|
479
|
-
`,
|
|
523
|
+
`, l = new Blob([f], { type: "application/javascript" }), d = this.trackWorker(new Worker(URL.createObjectURL(l)));
|
|
480
524
|
d.onmessage = (p) => {
|
|
481
|
-
|
|
525
|
+
this.terminateWorker(d), p.data.ok ? t(p.data.data) : s(new Error(p.data.error));
|
|
482
526
|
}, d.onerror = (p) => {
|
|
483
|
-
|
|
527
|
+
this.terminateWorker(d), s(p);
|
|
484
528
|
}, d.postMessage(i);
|
|
485
529
|
}),
|
|
486
530
|
succeeded: o.length,
|
|
@@ -515,23 +559,25 @@ class A {
|
|
|
515
559
|
* console.log(result); // final transformed + filtered data
|
|
516
560
|
*/
|
|
517
561
|
async pipeline(e) {
|
|
562
|
+
if (this._isTerminated)
|
|
563
|
+
throw new Error("MainWorkerFactory has been terminated");
|
|
518
564
|
if (e.length === 0)
|
|
519
565
|
throw new Error("Pipeline requires at least one step");
|
|
520
566
|
if (e.length === 1) {
|
|
521
567
|
const r = e[0], o = this.findWorkerByName(r.worker);
|
|
522
568
|
if (!o) throw new Error(`Worker "${r.worker}" not found`);
|
|
523
569
|
const i = this.initWorker(o).getWorker;
|
|
524
|
-
return new Promise((
|
|
570
|
+
return new Promise((c, u) => {
|
|
525
571
|
i.onmessage = (s) => {
|
|
526
|
-
var
|
|
527
|
-
|
|
572
|
+
var f, l;
|
|
573
|
+
this.terminateWorker(i), ((f = s.data) == null ? void 0 : f.ok) === !1 ? u(new Error(s.data.error)) : c((l = s.data) == null ? void 0 : l.data);
|
|
528
574
|
}, i.onerror = (s) => {
|
|
529
|
-
|
|
575
|
+
this.terminateWorker(i), u(s);
|
|
530
576
|
};
|
|
531
577
|
const t = r.srcData ?? {};
|
|
532
578
|
i.postMessage(
|
|
533
579
|
{ data: t, index: 0 },
|
|
534
|
-
|
|
580
|
+
k(t)
|
|
535
581
|
);
|
|
536
582
|
});
|
|
537
583
|
}
|
|
@@ -543,32 +589,32 @@ class A {
|
|
|
543
589
|
o(new Error(`Worker "${t.worker}" not found`));
|
|
544
590
|
return;
|
|
545
591
|
}
|
|
546
|
-
const
|
|
547
|
-
mode:
|
|
548
|
-
|
|
549
|
-
});
|
|
550
|
-
a.push(
|
|
592
|
+
const f = new g(s.func, {
|
|
593
|
+
mode: m.Pipeline,
|
|
594
|
+
createWorker: s.createWorker
|
|
595
|
+
}), l = this.trackWorker(f.getWorker);
|
|
596
|
+
a.push(l);
|
|
551
597
|
}
|
|
552
598
|
for (let t = 0; t < a.length - 1; t++)
|
|
553
599
|
i.push(new MessageChannel());
|
|
554
600
|
for (let t = 0; t < a.length; t++) {
|
|
555
|
-
const s = [],
|
|
556
|
-
t > 0 && (
|
|
557
|
-
{ __pipeline_ports__: !0, ...
|
|
601
|
+
const s = [], f = {};
|
|
602
|
+
t > 0 && (f.inputPort = i[t - 1].port1, s.push(f.inputPort)), t < a.length - 1 && (f.outputPort = i[t].port2, s.push(f.outputPort)), a[t].postMessage(
|
|
603
|
+
{ __pipeline_ports__: !0, ...f },
|
|
558
604
|
s
|
|
559
605
|
);
|
|
560
606
|
}
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
var s,
|
|
564
|
-
a.forEach((
|
|
565
|
-
},
|
|
566
|
-
a.forEach((s) =>
|
|
607
|
+
const c = a[a.length - 1];
|
|
608
|
+
c.onmessage = (t) => {
|
|
609
|
+
var s, f;
|
|
610
|
+
a.forEach((l) => this.terminateWorker(l)), ((s = t.data) == null ? void 0 : s.ok) === !1 ? o(new Error(t.data.error)) : r((f = t.data) == null ? void 0 : f.data);
|
|
611
|
+
}, c.onerror = (t) => {
|
|
612
|
+
a.forEach((s) => this.terminateWorker(s)), o(t);
|
|
567
613
|
};
|
|
568
|
-
const
|
|
614
|
+
const u = e[0].srcData ?? {};
|
|
569
615
|
a[0].postMessage(
|
|
570
|
-
{ data:
|
|
571
|
-
|
|
616
|
+
{ data: u, index: 0 },
|
|
617
|
+
k(u)
|
|
572
618
|
);
|
|
573
619
|
});
|
|
574
620
|
}
|
|
@@ -607,24 +653,30 @@ class A {
|
|
|
607
653
|
* factory.release('transform');
|
|
608
654
|
*/
|
|
609
655
|
async runPersistent(e, r) {
|
|
656
|
+
if (this._isTerminated)
|
|
657
|
+
throw new Error("MainWorkerFactory has been terminated");
|
|
610
658
|
const o = this.findWorkerByName(e);
|
|
611
659
|
if (!o) throw new Error(`Worker "${e}" not found`);
|
|
612
660
|
let a = this._persistentWorkers.get(e);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
661
|
+
if (!a) {
|
|
662
|
+
const i = new g(o.func, {
|
|
663
|
+
mode: m.Persistent,
|
|
664
|
+
createWorker: o.createWorker
|
|
665
|
+
});
|
|
666
|
+
a = this.trackWorker(i.getWorker), this._persistentWorkers.set(e, a);
|
|
667
|
+
}
|
|
668
|
+
return new Promise((i, c) => {
|
|
617
669
|
a.onmessage = (t) => {
|
|
618
|
-
var s,
|
|
619
|
-
((s = t.data) == null ? void 0 : s.ok) === !1 ?
|
|
670
|
+
var s, f;
|
|
671
|
+
((s = t.data) == null ? void 0 : s.ok) === !1 ? c(new Error(t.data.error)) : i((f = t.data) == null ? void 0 : f.data);
|
|
620
672
|
}, a.onerror = (t) => {
|
|
621
|
-
|
|
673
|
+
c(t);
|
|
622
674
|
};
|
|
623
|
-
const
|
|
675
|
+
const u = {
|
|
624
676
|
type: "run",
|
|
625
677
|
config: r.config
|
|
626
678
|
};
|
|
627
|
-
r.dataset !== void 0 && (
|
|
679
|
+
r.dataset !== void 0 && (u.dataset = r.dataset), a.postMessage(u, k(u));
|
|
628
680
|
});
|
|
629
681
|
}
|
|
630
682
|
/**
|
|
@@ -638,10 +690,55 @@ class A {
|
|
|
638
690
|
*/
|
|
639
691
|
release(e) {
|
|
640
692
|
const r = this._persistentWorkers.get(e);
|
|
641
|
-
|
|
693
|
+
if (r) {
|
|
694
|
+
try {
|
|
695
|
+
r.postMessage({ type: "release" });
|
|
696
|
+
} catch {
|
|
697
|
+
}
|
|
698
|
+
this.terminateWorker(r), this._persistentWorkers.delete(e);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Terminates the factory and all active and persistent worker instances.
|
|
703
|
+
*
|
|
704
|
+
* Calling `terminate()` immediately stops all running worker threads, releases
|
|
705
|
+
* cached persistent workers, and clears all internal worker state.
|
|
706
|
+
*/
|
|
707
|
+
terminate() {
|
|
708
|
+
this._isTerminated = !0;
|
|
709
|
+
for (const e of this._persistentWorkers.values()) {
|
|
710
|
+
try {
|
|
711
|
+
e.postMessage({ type: "release" });
|
|
712
|
+
} catch {
|
|
713
|
+
}
|
|
714
|
+
this.terminateWorker(e);
|
|
715
|
+
}
|
|
716
|
+
this._persistentWorkers.clear();
|
|
717
|
+
for (const e of Array.from(this._activeWorkers))
|
|
718
|
+
this.terminateWorker(e);
|
|
719
|
+
this._activeWorkers.clear();
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Alias for {@link terminate}. Terminates the factory and all worker instances.
|
|
723
|
+
*/
|
|
724
|
+
destroy() {
|
|
725
|
+
this.terminate();
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Resets the factory by terminating all active and persistent workers
|
|
729
|
+
* and resetting the factory state, allowing new worker instances to be initiated.
|
|
730
|
+
*/
|
|
731
|
+
reset() {
|
|
732
|
+
this.terminate(), this._isTerminated = !1;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Alias for {@link reset}. Resets the factory state to initiate new worker instances.
|
|
736
|
+
*/
|
|
737
|
+
restart() {
|
|
738
|
+
this.reset();
|
|
642
739
|
}
|
|
643
740
|
}
|
|
644
741
|
export {
|
|
645
|
-
|
|
646
|
-
|
|
742
|
+
E as MainWorkerFactory,
|
|
743
|
+
g as WorkerFactory
|
|
647
744
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { CollectOptions, CollectedResult, PipelineStep, WorkerConfig, WorkerConfigMap, WorkerDataParam, WorkerFunction, WorkerReturnType, TypedSettledResults } from './types.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Recursively collects all Transferable objects from a value.
|
|
4
|
-
*
|
|
4
|
+
* Transferable (ArrayBuffer, MessagePort, ImageBitmap, OffscreenCanvas)
|
|
5
5
|
* are zero-copy — they are moved to the worker instead of cloned.
|
|
6
6
|
*/
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function extractTransferable(value: unknown, seen?: Set<object>): Transferable[];
|
|
8
8
|
/**
|
|
9
9
|
* Central orchestrator for running typed Web Workers in parallel.
|
|
10
10
|
*
|
|
@@ -36,6 +36,8 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
36
36
|
private readonly _workers;
|
|
37
37
|
private readonly _threads;
|
|
38
38
|
private readonly _persistentWorkers;
|
|
39
|
+
private readonly _activeWorkers;
|
|
40
|
+
private _isTerminated;
|
|
39
41
|
/**
|
|
40
42
|
* Creates a new `MainWorkerFactory`.
|
|
41
43
|
*
|
|
@@ -44,10 +46,22 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
44
46
|
constructor(options: {
|
|
45
47
|
workers: TConfigs;
|
|
46
48
|
});
|
|
49
|
+
/**
|
|
50
|
+
* Returns `true` if the factory has been terminated.
|
|
51
|
+
*/
|
|
52
|
+
get isTerminated(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Registers an active worker instance for lifecycle tracking.
|
|
55
|
+
*/
|
|
56
|
+
private trackWorker;
|
|
57
|
+
/**
|
|
58
|
+
* Terminates a worker instance and removes it from tracking.
|
|
59
|
+
*/
|
|
60
|
+
private terminateWorker;
|
|
47
61
|
/**
|
|
48
62
|
* Instantiates a {@link WorkerFactory} for the given worker configuration.
|
|
49
63
|
*
|
|
50
|
-
* @param config - The worker configuration containing `func` or `
|
|
64
|
+
* @param config - The worker configuration containing `func` or `createWorker`.
|
|
51
65
|
* @returns A new `WorkerFactory` wrapping the worker.
|
|
52
66
|
*/
|
|
53
67
|
private initWorker;
|
|
@@ -144,10 +158,9 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
144
158
|
* Any transferable objects found in the payload are moved (not copied) to
|
|
145
159
|
* the worker via the `transfer` list of `postMessage`.
|
|
146
160
|
*
|
|
147
|
-
* The underlying `Worker` is always terminated after the
|
|
148
|
-
* whether it succeeded or failed.
|
|
161
|
+
* The underlying `Worker` is always terminated after the message completes.
|
|
149
162
|
*
|
|
150
|
-
* @param instanceConfig - Worker function,
|
|
163
|
+
* @param instanceConfig - Worker function, factory, name, shard index, and data.
|
|
151
164
|
* @returns A promise that resolves with the worker's result.
|
|
152
165
|
*/
|
|
153
166
|
private initiateWorker;
|
|
@@ -259,5 +272,25 @@ declare class MainWorkerFactory<TConfigs extends readonly WorkerConfig<WorkerFun
|
|
|
259
272
|
* @param workerName - Name of the persistent worker to release.
|
|
260
273
|
*/
|
|
261
274
|
release(workerName: string): void;
|
|
275
|
+
/**
|
|
276
|
+
* Terminates the factory and all active and persistent worker instances.
|
|
277
|
+
*
|
|
278
|
+
* Calling `terminate()` immediately stops all running worker threads, releases
|
|
279
|
+
* cached persistent workers, and clears all internal worker state.
|
|
280
|
+
*/
|
|
281
|
+
terminate(): void;
|
|
282
|
+
/**
|
|
283
|
+
* Alias for {@link terminate}. Terminates the factory and all worker instances.
|
|
284
|
+
*/
|
|
285
|
+
destroy(): void;
|
|
286
|
+
/**
|
|
287
|
+
* Resets the factory by terminating all active and persistent workers
|
|
288
|
+
* and resetting the factory state, allowing new worker instances to be initiated.
|
|
289
|
+
*/
|
|
290
|
+
reset(): void;
|
|
291
|
+
/**
|
|
292
|
+
* Alias for {@link reset}. Resets the factory state to initiate new worker instances.
|
|
293
|
+
*/
|
|
294
|
+
restart(): void;
|
|
262
295
|
}
|
|
263
296
|
export default MainWorkerFactory;
|
|
@@ -23,13 +23,14 @@ export interface WorkerConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
|
23
23
|
name: WorkerName;
|
|
24
24
|
/** Human-readable role label (e.g. `'compute'`, `'transform'`). */
|
|
25
25
|
role: WorkerRole;
|
|
26
|
-
/** The worker function that will be serialised and run in a thread. Optional if `
|
|
26
|
+
/** The worker function that will be serialised and run in a thread. Optional if `createWorker` is provided. */
|
|
27
27
|
func?: TFunc;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
* Enables
|
|
29
|
+
* Factory function returning a native `Worker` instance (e.g. `() => new Worker(new URL('./worker.ts', import.meta.url))`).
|
|
30
|
+
* Enables bundlers like Webpack 5, Vite, Rollup, and Parcel to statically analyze and bundle worker code into individual chunks,
|
|
31
|
+
* while allowing `MainWorkerFactory` to scale concurrency and manage worker thread lifecycles.
|
|
31
32
|
*/
|
|
32
|
-
|
|
33
|
+
createWorker?: () => Worker;
|
|
33
34
|
/**
|
|
34
35
|
* Maximum number of parallel threads to spawn for this worker.
|
|
35
36
|
* Defaults to `navigator.hardwareConcurrency` when omitted.
|
|
@@ -103,10 +104,10 @@ export interface MainWorkerFactoryWorker extends WorkerConfig {
|
|
|
103
104
|
export interface WorkerInstanceConfig<TFunc extends WorkerFunction = WorkerFunction> {
|
|
104
105
|
/** Name of the parent worker config, used in logs and error objects. */
|
|
105
106
|
workerName: WorkerName;
|
|
106
|
-
/** The function serialised and executed inside the thread (optional if `
|
|
107
|
+
/** The function serialised and executed inside the thread (optional if `createWorker` is set). */
|
|
107
108
|
workerFunc?: TFunc;
|
|
108
|
-
/**
|
|
109
|
-
|
|
109
|
+
/** Factory function returning a Worker instance. */
|
|
110
|
+
createWorker?: () => Worker;
|
|
110
111
|
/** Zero-based shard index assigned to this thread. */
|
|
111
112
|
index: number;
|
|
112
113
|
/** The data payload (full or partitioned shard) sent to the thread. */
|
|
@@ -7,8 +7,8 @@ export declare enum WorkerMode {
|
|
|
7
7
|
export interface WorkerFactoryOptions {
|
|
8
8
|
/** The worker execution mode. Defaults to `WorkerMode.Default`. */
|
|
9
9
|
mode?: WorkerMode;
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/** Factory function returning a native `Worker` instance. */
|
|
11
|
+
createWorker?: () => Worker;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Low-level factory that serializes a {@link WorkerFunction} into a Blob URL
|
|
@@ -34,16 +34,12 @@ export interface WorkerFactoryOptions {
|
|
|
34
34
|
declare class WorkerFactory {
|
|
35
35
|
readonly _worker: Worker;
|
|
36
36
|
/**
|
|
37
|
-
* Creates a new `Worker` from the given function.
|
|
38
|
-
*
|
|
39
|
-
* The function is stringified, embedded into a self-contained worker script,
|
|
40
|
-
* converted to a `Blob` URL, and passed to the `Worker` constructor.
|
|
37
|
+
* Creates a new `Worker` from the given function or factory option.
|
|
41
38
|
*
|
|
42
39
|
* @param workerFunction - The function to run inside the worker thread.
|
|
43
40
|
* Must be self-contained — it cannot reference variables from the outer
|
|
44
41
|
* scope because it is serialized via `.toString()`.
|
|
45
|
-
* @param options - Optional configuration
|
|
46
|
-
* worker execution mode (default, pipeline, or persistent).
|
|
42
|
+
* @param options - Optional configuration containing `createWorker` or `mode`.
|
|
47
43
|
*/
|
|
48
44
|
constructor(workerFunction?: WorkerFunction, options?: WorkerFactoryOptions);
|
|
49
45
|
/**
|
package/package.json
CHANGED