worker-lib 2.0.8 → 2.1.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 +65 -226
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node.js +1 -1
- package/dist/cjs/node.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node.js +1 -1
- package/dist/esm/node.js.map +1 -1
- package/package.json +8 -5
- package/tests/worker-script.ts +13 -0
- package/tests/worker.test.ts +42 -0
package/README.md
CHANGED
|
@@ -7,264 +7,103 @@
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
`worker-lib` is a lightweight, type-safe library designed to make **Web Workers** (Browser) and **worker_threads** (Node.js) as easy to use as standard asynchronous functions.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
createWorker,
|
|
15
|
-
initWorker,
|
|
16
|
-
waitAll,
|
|
17
|
-
waitReady,
|
|
18
|
-
close,
|
|
19
|
-
} from "worker-lib"; //auto
|
|
12
|
+
## Features
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
close,
|
|
27
|
-
} from "worker-lib/node"; // Node.js worker_threads
|
|
14
|
+
- **🚀 Cross-Platform**: Supports both Browser and Node.js with a unified API.
|
|
15
|
+
- **🛡️ Type-Safe**: Full TypeScript support with automatic type inference for worker functions.
|
|
16
|
+
- **⚡ Parallelism**: Built-in worker pool management with configurable concurrency limits.
|
|
17
|
+
- **🔄 Callback Support**: Pass functions as arguments to workers for progress updates or event handling.
|
|
18
|
+
- **📦 Zero Config**: Minimal setup required to get started.
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
createWorker,
|
|
31
|
-
initWorker,
|
|
32
|
-
waitAll,
|
|
33
|
-
waitReady,
|
|
34
|
-
close,
|
|
35
|
-
} from "worker-lib/web-worker"; // Web Worker
|
|
36
|
-
```
|
|
20
|
+
## Installation
|
|
37
21
|
|
|
38
|
-
|
|
22
|
+
```bash
|
|
23
|
+
npm install worker-lib
|
|
24
|
+
# or
|
|
25
|
+
pnpm add worker-lib
|
|
26
|
+
```
|
|
39
27
|
|
|
40
|
-
|
|
28
|
+
## Basic Usage
|
|
41
29
|
|
|
42
|
-
###
|
|
30
|
+
### 1. Define Worker (worker.ts)
|
|
43
31
|
|
|
44
|
-
|
|
32
|
+
Register your functions using `initWorker`.
|
|
45
33
|
|
|
46
34
|
```ts
|
|
47
35
|
import { initWorker } from "worker-lib";
|
|
48
36
|
|
|
49
|
-
const add = (a: number, b: number) =>
|
|
50
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
51
|
-
return a + b;
|
|
52
|
-
};
|
|
53
|
-
const add2 = (a: string, b: string) => {
|
|
54
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
55
|
-
return a + b;
|
|
56
|
-
};
|
|
57
|
-
const sub = (a: number, b: number) => {
|
|
58
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
59
|
-
return a - b;
|
|
60
|
-
};
|
|
61
|
-
const mul = (a: number, b: number) => {
|
|
62
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
63
|
-
return a * b;
|
|
64
|
-
};
|
|
37
|
+
const add = (a: number, b: number) => a + b;
|
|
65
38
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
39
|
+
const heavyTask = async (data: string, onProgress: (percent: number, status: string) => void) => {
|
|
40
|
+
onProgress(10, "Starting...");
|
|
41
|
+
// ... heavy computation ...
|
|
42
|
+
onProgress(100, "Done");
|
|
43
|
+
return `Processed: ${data}`;
|
|
70
44
|
};
|
|
71
45
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// Export only the type
|
|
75
|
-
export type WorkerTest = typeof map;
|
|
46
|
+
const workerMap = initWorker({ add, heavyTask });
|
|
47
|
+
export type MyWorker = typeof workerMap;
|
|
76
48
|
```
|
|
77
49
|
|
|
78
|
-
|
|
50
|
+
### 2. Use Worker in Main Thread
|
|
51
|
+
|
|
52
|
+
#### Node.js (worker_threads)
|
|
79
53
|
|
|
80
54
|
```ts
|
|
81
55
|
import { Worker } from "node:worker_threads";
|
|
82
|
-
import { createWorker } from "worker-lib";
|
|
83
|
-
import type {
|
|
56
|
+
import { createWorker } from "worker-lib/node";
|
|
57
|
+
import type { MyWorker } from "./worker";
|
|
84
58
|
import path from "node:path";
|
|
85
59
|
|
|
86
|
-
const { execute, close } = createWorker<
|
|
87
|
-
() => new Worker(path.resolve(__dirname, "./worker
|
|
88
|
-
4 //
|
|
60
|
+
const { execute, close } = createWorker<MyWorker>(
|
|
61
|
+
() => new Worker(path.resolve(__dirname, "./worker.js")),
|
|
62
|
+
4 // Max parallel workers
|
|
89
63
|
);
|
|
90
64
|
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const b = 100;
|
|
94
|
-
const p = [
|
|
95
|
-
execute("add", a, b).then((result) => {
|
|
96
|
-
console.log("add", result);
|
|
97
|
-
}),
|
|
98
|
-
execute("add2", a.toString(), b.toString()).then((result) => {
|
|
99
|
-
console.log("add2", result);
|
|
100
|
-
}),
|
|
101
|
-
execute("sub", a, b).then((result) => {
|
|
102
|
-
console.log("sub", result);
|
|
103
|
-
}),
|
|
104
|
-
execute("mul", a, b).then((result) => {
|
|
105
|
-
console.log("sub", result);
|
|
106
|
-
}),
|
|
107
|
-
execute("error", a, b)
|
|
108
|
-
.then((result) => {
|
|
109
|
-
console.log("error", result);
|
|
110
|
-
})
|
|
111
|
-
.catch((e) => {
|
|
112
|
-
console.error("error", e);
|
|
113
|
-
}),
|
|
114
|
-
];
|
|
115
|
-
console.log("Start");
|
|
116
|
-
await Promise.all(p);
|
|
117
|
-
close(); // Close the worker
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
main();
|
|
65
|
+
const result = await execute("add", 10, 20);
|
|
66
|
+
console.log(result); // 30
|
|
121
67
|
```
|
|
122
68
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
- src/libs/worker-test.ts
|
|
69
|
+
#### Browser / Next.js (Web Worker)
|
|
126
70
|
|
|
127
71
|
```ts
|
|
128
|
-
import {
|
|
129
|
-
|
|
130
|
-
const add = (a: number, b: number) => {
|
|
131
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
132
|
-
return a + b;
|
|
133
|
-
};
|
|
134
|
-
const add2 = (a: string, b: string) => {
|
|
135
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
136
|
-
return a + b;
|
|
137
|
-
};
|
|
138
|
-
const sub = (a: number, b: number) => {
|
|
139
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
140
|
-
return a - b;
|
|
141
|
-
};
|
|
142
|
-
const mul = (a: number, b: number) => {
|
|
143
|
-
for (let i = 0; i < 1000000000; i++); //Overload unnecessarily
|
|
144
|
-
return a * b;
|
|
145
|
-
};
|
|
72
|
+
import { createWorker } from "worker-lib";
|
|
73
|
+
import type { MyWorker } from "./worker";
|
|
146
74
|
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
75
|
+
const { execute } = createWorker<MyWorker>(
|
|
76
|
+
() => new Worker(new URL("./worker.ts", import.meta.url)),
|
|
77
|
+
5
|
|
78
|
+
);
|
|
152
79
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
export type WorkerTest = typeof map;
|
|
80
|
+
const result = await execute("heavyTask", "input-data", (percent, status) => {
|
|
81
|
+
console.log(`[${status}] ${percent}%`);
|
|
82
|
+
});
|
|
157
83
|
```
|
|
158
84
|
|
|
159
|
-
|
|
85
|
+
## API Reference
|
|
160
86
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
import { createWorker } from "worker-lib";
|
|
165
|
-
import type { WorkerTest } from "../libs/worker-test";
|
|
87
|
+
### `initWorker(workerProcess)`
|
|
88
|
+
Initializes the worker side.
|
|
89
|
+
- `workerProcess`: An object containing the functions to be exposed.
|
|
166
90
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
5 // Maximum parallel number
|
|
172
|
-
);
|
|
91
|
+
### `createWorker(builder, limit?)`
|
|
92
|
+
Creates a worker pool.
|
|
93
|
+
- `builder`: A function that returns a new `Worker` instance.
|
|
94
|
+
- `limit`: (Optional) Maximum number of concurrent workers. Default is `4`.
|
|
173
95
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
96
|
+
### `execute(name, ...args)`
|
|
97
|
+
Executes a worker function.
|
|
98
|
+
- `name`: The name of the function to execute.
|
|
99
|
+
- `args`: Arguments to pass to the function (supports callbacks).
|
|
178
100
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
name="b"
|
|
189
|
-
value={b}
|
|
190
|
-
onChange={(e) => setB(Number(e.currentTarget.value))}
|
|
191
|
-
/>
|
|
192
|
-
<button
|
|
193
|
-
type="button"
|
|
194
|
-
onClick={async () => {
|
|
195
|
-
const index = values.length;
|
|
196
|
-
setValues([...values, "running"]);
|
|
197
|
-
//Calling a Worker
|
|
198
|
-
const result = await execute("add", a, b);
|
|
199
|
-
setValues((values) =>
|
|
200
|
-
values.map((v, i) => (i === index ? result : v))
|
|
201
|
-
);
|
|
202
|
-
}}
|
|
203
|
-
>
|
|
204
|
-
Add
|
|
205
|
-
</button>
|
|
206
|
-
<button
|
|
207
|
-
type="button"
|
|
208
|
-
onClick={async () => {
|
|
209
|
-
const index = values.length;
|
|
210
|
-
setValues([...values, "running"]);
|
|
211
|
-
//Calling a Worker
|
|
212
|
-
const result = await execute("add2", String(a), String(b));
|
|
213
|
-
setValues((values) =>
|
|
214
|
-
values.map((v, i) => (i === index ? result : v))
|
|
215
|
-
);
|
|
216
|
-
}}
|
|
217
|
-
>
|
|
218
|
-
Add(String)
|
|
219
|
-
</button>
|
|
220
|
-
<button
|
|
221
|
-
type="button"
|
|
222
|
-
onClick={async () => {
|
|
223
|
-
const index = values.length;
|
|
224
|
-
setValues([...values, "running"]);
|
|
225
|
-
//Calling a Worker
|
|
226
|
-
const result = await execute("sub", a, b);
|
|
227
|
-
setValues((values) =>
|
|
228
|
-
values.map((v, i) => (i === index ? result : v))
|
|
229
|
-
);
|
|
230
|
-
}}
|
|
231
|
-
>
|
|
232
|
-
Sub
|
|
233
|
-
</button>
|
|
234
|
-
<button
|
|
235
|
-
type="button"
|
|
236
|
-
onClick={async () => {
|
|
237
|
-
const index = values.length;
|
|
238
|
-
setValues([...values, "running"]);
|
|
239
|
-
//Calling a Worker
|
|
240
|
-
const result = await execute("mul", a, b);
|
|
241
|
-
setValues((values) =>
|
|
242
|
-
values.map((v, i) => (i === index ? result : v))
|
|
243
|
-
);
|
|
244
|
-
}}
|
|
245
|
-
>
|
|
246
|
-
Mul
|
|
247
|
-
</button>
|
|
248
|
-
<button
|
|
249
|
-
type="button"
|
|
250
|
-
onClick={async () => {
|
|
251
|
-
const index = values.length;
|
|
252
|
-
setValues([...values, "running"]);
|
|
253
|
-
//Calling a Worker
|
|
254
|
-
const result = await execute("error", a, b).catch((e) => e);
|
|
255
|
-
setValues((values) =>
|
|
256
|
-
values.map((v, i) => (i === index ? result : v))
|
|
257
|
-
);
|
|
258
|
-
}}
|
|
259
|
-
>
|
|
260
|
-
Error
|
|
261
|
-
</button>
|
|
262
|
-
</form>
|
|
263
|
-
{values.map((v, index) => (
|
|
264
|
-
<div key={index}>{v}</div>
|
|
265
|
-
))}
|
|
266
|
-
</div>
|
|
267
|
-
);
|
|
268
|
-
};
|
|
269
|
-
export default Page;
|
|
270
|
-
```
|
|
101
|
+
### `waitAll()`
|
|
102
|
+
Returns a promise that resolves when all currently running tasks are complete.
|
|
103
|
+
|
|
104
|
+
### `close()`
|
|
105
|
+
Terminates all workers in the pool.
|
|
106
|
+
|
|
107
|
+
## Examples
|
|
108
|
+
|
|
109
|
+
For more detailed examples, check the [samples repository](https://github.com/SoraKumo001/worker-lib-samples/).
|
package/dist/cjs/index.js
CHANGED
|
@@ -14,7 +14,7 @@ const exec = (worker, name, ...value) => {
|
|
|
14
14
|
const { data } = result;
|
|
15
15
|
switch (data.type) {
|
|
16
16
|
case "callback":
|
|
17
|
-
const r = value[data.payload.index](data.payload.value);
|
|
17
|
+
const r = value[data.payload.index](...data.payload.value);
|
|
18
18
|
worker.postMessage({
|
|
19
19
|
type: "callback_result",
|
|
20
20
|
payload: { id: data.payload.id, result: await r },
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) => callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
package/dist/cjs/node.js
CHANGED
|
@@ -14,7 +14,7 @@ const exec = (worker, name, ...value) => {
|
|
|
14
14
|
const p = async (data) => {
|
|
15
15
|
switch (data.type) {
|
|
16
16
|
case "callback":
|
|
17
|
-
const r = value[data.payload.index](data.payload.value);
|
|
17
|
+
const r = value[data.payload.index](...data.payload.value);
|
|
18
18
|
worker.postMessage({
|
|
19
19
|
type: "callback_result",
|
|
20
20
|
payload: { id: data.payload.id, result: await r },
|
package/dist/cjs/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
package/dist/esm/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const exec = (worker, name, ...value) => {
|
|
|
11
11
|
const { data } = result;
|
|
12
12
|
switch (data.type) {
|
|
13
13
|
case "callback":
|
|
14
|
-
const r = value[data.payload.index](data.payload.value);
|
|
14
|
+
const r = value[data.payload.index](...data.payload.value);
|
|
15
15
|
worker.postMessage({
|
|
16
16
|
type: "callback_result",
|
|
17
17
|
payload: { id: data.payload.id, result: await r },
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) => callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Worker as WorkerNode } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n () => {\n resolve(worker);\n },\n { once: true }\n );\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (result: MessageEvent<WorkerSendEvent<T>>) => {\n const { data } = result;\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeEventListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeEventListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addEventListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker =\n result instanceof Worker\n ? result\n : new Worker(result as string | URL);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = self as unknown as Worker;\n worker.addEventListener(\"message\", async (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.addEventListener(\n \"message\",\n (e: MessageEvent) => {\n const data = e.data as WorkerRecvEvent<T>;\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n },\n { once: true }\n );\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
package/dist/esm/node.js
CHANGED
|
@@ -11,7 +11,7 @@ const exec = (worker, name, ...value) => {
|
|
|
11
11
|
const p = async (data) => {
|
|
12
12
|
switch (data.type) {
|
|
13
13
|
case "callback":
|
|
14
|
-
const r = value[data.payload.index](data.payload.value);
|
|
14
|
+
const r = value[data.payload.index](...data.payload.value);
|
|
15
15
|
worker.postMessage({
|
|
16
16
|
type: "callback_result",
|
|
17
17
|
payload: { id: data.payload.id, result: await r },
|
package/dist/esm/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype WorkerRecvEvent<T> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: { id: number; result: unknown; index: number; value: T };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: unknown[]) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T>(worker: Worker, index: number, params: unknown[]) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, Worker } from \"node:worker_threads\";\ntype WorkerType = { [key: string]: (...args: any) => any };\ntype CallbackValue<T extends WorkerType> = Parameters<\n Extract<Parameters<T[keyof T]>[number], (...args: any) => any>\n>;\ntype WorkerRecvEvent<T extends WorkerType> =\n | {\n type: \"function\";\n payload: { name: keyof T; callback: boolean[]; value: unknown[] };\n }\n | { type: \"callback_result\"; payload: { id: number; result: unknown } };\ntype WorkerSendEvent<T extends WorkerType> =\n | {\n type: \"callback\";\n payload: {\n id: number;\n result: unknown;\n index: number;\n value: CallbackValue<T>;\n };\n }\n | {\n type: \"result\";\n payload: ReturnType<T[keyof T]>;\n }\n | {\n type: \"error\";\n payload: unknown;\n };\n\nconst init = (worker: Worker): Promise<Worker> => {\n return new Promise((resolve) => {\n worker.once(\"message\", () => {\n resolve(worker);\n });\n });\n};\nconst exec = <T extends WorkerType>(\n worker: Worker,\n name: keyof T,\n ...value: Parameters<T[keyof T]>\n): Promise<ReturnType<T[keyof T]>> => {\n return new Promise((resolve, reject) => {\n const p = async (data: WorkerSendEvent<T>) => {\n switch (data.type) {\n case \"callback\":\n const r = value[data.payload.index](...data.payload.value);\n worker.postMessage({\n type: \"callback_result\",\n payload: { id: data.payload.id, result: await r },\n });\n break;\n case \"result\":\n worker.removeListener(\"message\", p);\n resolve(data.payload);\n break;\n case \"error\":\n worker.removeListener(\"message\", p);\n reject(data.payload);\n break;\n }\n };\n worker.addListener(\"message\", p);\n worker.postMessage({\n type: \"function\",\n payload: {\n name,\n value: value.map((v: unknown) => !(typeof v === \"function\") && v),\n callback: value.map((v: unknown) => typeof v === \"function\"),\n },\n } as WorkerRecvEvent<T>);\n });\n};\n\n/**\n * Creates a worker pool with a specified limit of concurrent workers.\n *\n * @template T - The type of the worker.\n * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.\n * @param {number} [limit=4] - The maximum number of concurrent workers.\n * @returns {{\n * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,\n * waitAll: () => Promise<void>,\n * waitReady: (retryTime?: number) => Promise<void>,\n * close: () => void,\n * setLimit: (limit: number) => void,\n * launchWorker: () => Promise<void[]>\n * }} An object containing methods to interact with the worker pool.\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | string | URL,\n limit = 4\n) => {\n let workers: {\n worker?: Worker;\n resultResolver?: PromiseWithResolvers<unknown>;\n }[] = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n const emptyWaits: PromiseWithResolvers<void>[] = [];\n let isEmptyWait = false;\n\n const getResolver = async () => {\n while (true) {\n const target = workers.find(({ resultResolver }) => !resultResolver);\n if (target) {\n target.resultResolver = Promise.withResolvers<unknown>();\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\n\n /**\n * @method execute - Executes a method on a worker.\n * @template K - The key of the method to execute.\n * @param {K} name - The name of the method to execute.\n * @param {...Parameters<T[K]>} value - The arguments to pass to the method.\n * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.\n */\n const execute = async <K extends keyof T>(\n name: K,\n ...value: Parameters<T[K]>\n ): Promise<Awaited<ReturnType<T[K]>>> => {\n const target = await getResolver();\n const { resultResolver } = target;\n if (!resultResolver) throw new Error(\"Unexpected error\");\n exec(target.worker!, name as string, ...value)\n .then(resultResolver.resolve)\n .catch(resultResolver.reject)\n .finally(() => {\n target.resultResolver = undefined;\n });\n return resultResolver.promise as Promise<Awaited<ReturnType<T[K]>>>;\n };\n\n /**\n * @method launchWorker - Launches all workers in the pool.\n * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.\n */\n const launchWorker = async () => {\n return Promise.all(\n workers.map(async (target) => {\n if (!target.worker) {\n const result = builder();\n const worker = result instanceof Worker ? result : new Worker(result);\n target.worker = await init(worker);\n }\n })\n );\n };\n\n /**\n * @method waitAll - Waits for all workers to complete their tasks.\n * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.\n */\n const waitAll = async () => {\n while (workers.find(({ resultResolver }) => resultResolver)) {\n await Promise.all(\n workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n )\n );\n }\n };\n\n /**\n * @method waitReady - Waits for the worker pool to be ready.\n * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.\n * @returns {Promise<void>} A promise that resolves when the worker pool is ready.\n */\n const waitReady = async (retryTime = 1) => {\n const p = Promise.withResolvers<void>();\n emptyWaits.push(p);\n (async () => {\n if (!isEmptyWait) {\n isEmptyWait = true;\n do {\n const actives = workers.flatMap(({ resultResolver }) =>\n resultResolver ? [resultResolver.promise] : []\n );\n if (workers.length === actives.length) await Promise.race(actives);\n emptyWaits.shift()?.resolve();\n if (retryTime) await new Promise((r) => setTimeout(r, retryTime));\n else await Promise.resolve();\n } while (emptyWaits.length);\n isEmptyWait = false;\n }\n })();\n return p.promise;\n };\n\n /**\n * @method close - Terminates all workers in the pool.\n */\n const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\n };\n\n /**\n * @method setLimit - Sets a new limit for the number of concurrent workers.\n * @param {number} limit - The new limit for the number of concurrent workers.\n */\n const setLimit = (limit: number) => {\n workers.forEach((w) => w.worker?.terminate());\n workers = Array(limit)\n .fill(undefined)\n .map(() => ({}));\n };\n return { execute, waitAll, waitReady, close, setLimit, launchWorker };\n};\n\n/**\n * Initializes a web worker with the provided worker process.\n *\n * @template T - The type of the worker process.\n * @param {T} WorkerProc - The worker process to initialize.\n * @returns {T} The initialized worker process.\n */\nexport const initWorker = <T extends WorkerType>(WorkerProc: T) => {\n const worker = parentPort;\n if (!worker) {\n throw new Error(\"This is not a worker thread\");\n }\n worker.addListener(\"message\", async (data: WorkerRecvEvent<T>) => {\n if (data.type === \"function\") {\n const {\n name,\n value,\n callback,\n }: {\n name: keyof T;\n value: unknown[];\n callback: boolean[];\n } = data.payload;\n const proc = WorkerProc[name];\n if (proc) {\n try {\n const params = value.map((v, index) =>\n callback[index]\n ? (...params: CallbackValue<T>) =>\n callbackProc<T>(worker as never, index, params)\n : v\n );\n worker.postMessage({\n type: \"result\",\n payload: await proc(...params),\n });\n } catch (e) {\n worker.postMessage({ type: \"error\", payload: String(e) });\n }\n }\n }\n });\n worker.postMessage(undefined);\n return WorkerProc;\n};\n\nconst callbackProc = <T extends WorkerType>(\n worker: Worker,\n index: number,\n params: CallbackValue<T>\n) => {\n const id = WorkerValue.id++;\n return new Promise((resolve) => {\n worker.once(\"message\", (data: WorkerRecvEvent<T>) => {\n if (data.type === \"callback_result\" && data.payload.id === id) {\n resolve(data.payload.result);\n }\n });\n worker.postMessage({\n type: \"callback\",\n payload: { id, index, value: params },\n });\n });\n};\n\nconst WorkerValue = { id: 0, promises: {} } as {\n id: number;\n promises: { [key: number]: Promise<unknown> };\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "worker-lib",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"main": "./dist/cjs/index.js",
|
|
5
5
|
"types": "./dist/cjs/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -45,12 +45,15 @@
|
|
|
45
45
|
},
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsc && tsc --project ./tsconfig.esm.json && cpy esm dist"
|
|
48
|
+
"build": "tsc && tsc --project ./tsconfig.esm.json && cpy esm dist",
|
|
49
|
+
"test": "vitest run"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
|
-
"@types/node": "
|
|
52
|
-
"cpy-cli": "
|
|
53
|
-
"
|
|
52
|
+
"@types/node": "25.2.3",
|
|
53
|
+
"cpy-cli": "7.0.0",
|
|
54
|
+
"tsx": "4.21.0",
|
|
55
|
+
"typescript": "^5.9.3",
|
|
56
|
+
"vitest": "4.0.18"
|
|
54
57
|
},
|
|
55
58
|
"description": "Library for easy use of web-worker",
|
|
56
59
|
"repository": {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { initWorker } from "../src/node";
|
|
2
|
+
|
|
3
|
+
const add = (a: number, b: number) => a + b;
|
|
4
|
+
|
|
5
|
+
const asyncTask = async (onProgress: (percent: number, status: string) => void) => {
|
|
6
|
+
onProgress(10, "starting");
|
|
7
|
+
onProgress(50, "halfway");
|
|
8
|
+
onProgress(100, "done");
|
|
9
|
+
return "task-result";
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const map = initWorker({ add, asyncTask });
|
|
13
|
+
export type TestWorker = typeof map;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { describe, it, expect, afterAll } from "vitest";
|
|
2
|
+
import { createWorker } from "../src/node";
|
|
3
|
+
import type { TestWorker } from "./worker-script";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
describe("worker-lib node", () => {
|
|
7
|
+
const { execute, close } = createWorker<TestWorker>(
|
|
8
|
+
() => {
|
|
9
|
+
// Use tsx to run the TypeScript worker file directly
|
|
10
|
+
const workerPath = path.resolve(__dirname, "./worker-script.ts");
|
|
11
|
+
const normalizedPath = workerPath.split(path.sep).join("/");
|
|
12
|
+
return new (require("node:worker_threads").Worker)(
|
|
13
|
+
`require('tsx/cjs'); require('${normalizedPath}');`,
|
|
14
|
+
{ eval: true }
|
|
15
|
+
);
|
|
16
|
+
},
|
|
17
|
+
2
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
afterAll(() => {
|
|
21
|
+
close();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should execute a simple function", async () => {
|
|
25
|
+
const result = await execute("add", 10, 20);
|
|
26
|
+
expect(result).toBe(30);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should execute a function with callbacks", async () => {
|
|
30
|
+
const progress: { percent: number; status: string }[] = [];
|
|
31
|
+
|
|
32
|
+
const result = await execute("asyncTask", (percent, status) => {
|
|
33
|
+
progress.push({ percent, status });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(result).toBe("task-result");
|
|
37
|
+
expect(progress).toHaveLength(3);
|
|
38
|
+
expect(progress[0]).toEqual({ percent: 10, status: "starting" });
|
|
39
|
+
expect(progress[1]).toEqual({ percent: 50, status: "halfway" });
|
|
40
|
+
expect(progress[2]).toEqual({ percent: 100, status: "done" });
|
|
41
|
+
});
|
|
42
|
+
});
|