worker-lib 2.0.5 → 2.0.7

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.
@@ -3,26 +3,34 @@ type WorkerType = {
3
3
  [key: string]: (...args: any) => any;
4
4
  };
5
5
  /**
6
- * createWorker
6
+ * Creates a worker pool with a specified limit of concurrent workers.
7
7
  *
8
- * @template T
9
- * @param {() => Worker} builder
10
- * @param {number} [limit=0]
11
- * @return {*}
8
+ * @template T - The type of the worker.
9
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
10
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
11
+ * @returns {{
12
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
13
+ * waitAll: () => Promise<void>,
14
+ * waitReady: (retryTime?: number) => Promise<void>,
15
+ * close: () => void,
16
+ * setLimit: (limit: number) => void,
17
+ * launchWorker: () => Promise<void[]>
18
+ * }} An object containing methods to interact with the worker pool.
12
19
  */
13
- export declare const createWorker: <T extends WorkerType>(builder: () => Worker | WorkerNode, limit?: number) => {
20
+ export declare const createWorker: <T extends WorkerType>(builder: () => Worker | WorkerNode | string | URL, limit?: number) => {
14
21
  execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>;
15
22
  waitAll: () => Promise<void>;
16
23
  waitReady: (retryTime?: number) => Promise<void>;
17
24
  close: () => void;
18
25
  setLimit: (limit: number) => void;
26
+ launchWorker: () => Promise<void[]>;
19
27
  };
20
28
  /**
29
+ * Initializes a web worker with the provided worker process.
21
30
  *
22
- *
23
- * @template T
24
- * @param {T} WorkerProc
25
- * @return {*}
31
+ * @template T - The type of the worker process.
32
+ * @param {T} WorkerProc - The worker process to initialize.
33
+ * @returns {T} The initialized worker process.
26
34
  */
27
35
  export declare const initWorker: <T extends WorkerType>(WorkerProc: T) => T;
28
36
  export {};
package/dist/cjs/index.js CHANGED
@@ -42,12 +42,19 @@ const exec = (worker, name, ...value) => {
42
42
  });
43
43
  };
44
44
  /**
45
- * createWorker
45
+ * Creates a worker pool with a specified limit of concurrent workers.
46
46
  *
47
- * @template T
48
- * @param {() => Worker} builder
49
- * @param {number} [limit=0]
50
- * @return {*}
47
+ * @template T - The type of the worker.
48
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
49
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
50
+ * @returns {{
51
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
52
+ * waitAll: () => Promise<void>,
53
+ * waitReady: (retryTime?: number) => Promise<void>,
54
+ * close: () => void,
55
+ * setLimit: (limit: number) => void,
56
+ * launchWorker: () => Promise<void[]>
57
+ * }} An object containing methods to interact with the worker pool.
51
58
  */
52
59
  const createWorker = (builder, limit = 4) => {
53
60
  let workers = Array(limit)
@@ -60,13 +67,25 @@ const createWorker = (builder, limit = 4) => {
60
67
  const target = workers.find(({ resultResolver }) => !resultResolver);
61
68
  if (target) {
62
69
  target.resultResolver = Promise.withResolvers();
63
- if (!target.worker)
64
- target.worker = await init(builder());
70
+ if (!target.worker) {
71
+ const result = builder();
72
+ const worker = result instanceof Worker
73
+ ? result
74
+ : new Worker(result);
75
+ target.worker = await init(worker);
76
+ }
65
77
  return target;
66
78
  }
67
79
  await Promise.race(workers.map(({ resultResolver }) => resultResolver?.promise));
68
80
  }
69
81
  };
82
+ /**
83
+ * @method execute - Executes a method on a worker.
84
+ * @template K - The key of the method to execute.
85
+ * @param {K} name - The name of the method to execute.
86
+ * @param {...Parameters<T[K]>} value - The arguments to pass to the method.
87
+ * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.
88
+ */
70
89
  const execute = async (name, ...value) => {
71
90
  const target = await getResolver();
72
91
  const { resultResolver } = target;
@@ -80,11 +99,35 @@ const createWorker = (builder, limit = 4) => {
80
99
  });
81
100
  return resultResolver.promise;
82
101
  };
102
+ /**
103
+ * @method launchWorker - Launches all workers in the pool.
104
+ * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.
105
+ */
106
+ const launchWorker = async () => {
107
+ return Promise.all(workers.map(async (target) => {
108
+ if (!target.worker) {
109
+ const result = builder();
110
+ const worker = result instanceof Worker
111
+ ? result
112
+ : new Worker(result);
113
+ target.worker = await init(worker);
114
+ }
115
+ }));
116
+ };
117
+ /**
118
+ * @method waitAll - Waits for all workers to complete their tasks.
119
+ * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.
120
+ */
83
121
  const waitAll = async () => {
84
122
  while (workers.find(({ resultResolver }) => resultResolver)) {
85
123
  await Promise.all(workers.flatMap(({ resultResolver }) => resultResolver ? [resultResolver.promise] : []));
86
124
  }
87
125
  };
126
+ /**
127
+ * @method waitReady - Waits for the worker pool to be ready.
128
+ * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.
129
+ * @returns {Promise<void>} A promise that resolves when the worker pool is ready.
130
+ */
88
131
  const waitReady = async (retryTime = 1) => {
89
132
  const p = Promise.withResolvers();
90
133
  emptyWaits.push(p);
@@ -106,26 +149,33 @@ const createWorker = (builder, limit = 4) => {
106
149
  })();
107
150
  return p.promise;
108
151
  };
152
+ /**
153
+ * @method close - Terminates all workers in the pool.
154
+ */
109
155
  const close = () => {
110
156
  for (const { worker } of workers) {
111
157
  worker?.terminate();
112
158
  }
113
159
  };
160
+ /**
161
+ * @method setLimit - Sets a new limit for the number of concurrent workers.
162
+ * @param {number} limit - The new limit for the number of concurrent workers.
163
+ */
114
164
  const setLimit = (limit) => {
115
165
  workers.forEach((w) => w.worker?.terminate());
116
166
  workers = Array(limit)
117
167
  .fill(undefined)
118
168
  .map(() => ({}));
119
169
  };
120
- return { execute, waitAll, waitReady, close, setLimit };
170
+ return { execute, waitAll, waitReady, close, setLimit, launchWorker };
121
171
  };
122
172
  exports.createWorker = createWorker;
123
173
  /**
174
+ * Initializes a web worker with the provided worker process.
124
175
  *
125
- *
126
- * @template T
127
- * @param {T} WorkerProc
128
- * @return {*}
176
+ * @template T - The type of the worker process.
177
+ * @param {T} WorkerProc - The worker process to initialize.
178
+ * @returns {T} The initialized worker process.
129
179
  */
130
180
  const initWorker = (WorkerProc) => {
131
181
  const worker = self;
@@ -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 * createWorker\n *\n * @template T\n * @param {() => Worker} builder\n * @param {number} [limit=0]\n * @return {*}\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode,\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) target.worker = await init(builder() as Worker);\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\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 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 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 const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\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 };\n};\n/**\n *\n *\n * @template T\n * @param {T} WorkerProc\n * @return {*}\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 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,28 +1,36 @@
1
- import { type Worker } from "node:worker_threads";
1
+ import { Worker } from "node:worker_threads";
2
2
  type WorkerType = {
3
3
  [key: string]: (...args: any) => any;
4
4
  };
5
5
  /**
6
- * createWorker
6
+ * Creates a worker pool with a specified limit of concurrent workers.
7
7
  *
8
- * @template T
9
- * @param {() => Worker} builder
10
- * @param {number} [limit=0]
11
- * @return {*}
8
+ * @template T - The type of the worker.
9
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
10
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
11
+ * @returns {{
12
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
13
+ * waitAll: () => Promise<void>,
14
+ * waitReady: (retryTime?: number) => Promise<void>,
15
+ * close: () => void,
16
+ * setLimit: (limit: number) => void,
17
+ * launchWorker: () => Promise<void[]>
18
+ * }} An object containing methods to interact with the worker pool.
12
19
  */
13
- export declare const createWorker: <T extends WorkerType>(builder: () => Worker, limit?: number) => {
20
+ export declare const createWorker: <T extends WorkerType>(builder: () => Worker | string | URL, limit?: number) => {
14
21
  execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>;
15
22
  waitAll: () => Promise<void>;
16
23
  waitReady: (retryTime?: number) => Promise<void>;
17
24
  close: () => void;
18
25
  setLimit: (limit: number) => void;
26
+ launchWorker: () => Promise<void[]>;
19
27
  };
20
28
  /**
29
+ * Initializes a web worker with the provided worker process.
21
30
  *
22
- *
23
- * @template T
24
- * @param {T} WorkerProc
25
- * @return {*}
31
+ * @template T - The type of the worker process.
32
+ * @param {T} WorkerProc - The worker process to initialize.
33
+ * @returns {T} The initialized worker process.
26
34
  */
27
35
  export declare const initWorker: <T extends WorkerType>(WorkerProc: T) => T;
28
36
  export {};
package/dist/cjs/node.js CHANGED
@@ -42,12 +42,19 @@ const exec = (worker, name, ...value) => {
42
42
  });
43
43
  };
44
44
  /**
45
- * createWorker
45
+ * Creates a worker pool with a specified limit of concurrent workers.
46
46
  *
47
- * @template T
48
- * @param {() => Worker} builder
49
- * @param {number} [limit=0]
50
- * @return {*}
47
+ * @template T - The type of the worker.
48
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
49
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
50
+ * @returns {{
51
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
52
+ * waitAll: () => Promise<void>,
53
+ * waitReady: (retryTime?: number) => Promise<void>,
54
+ * close: () => void,
55
+ * setLimit: (limit: number) => void,
56
+ * launchWorker: () => Promise<void[]>
57
+ * }} An object containing methods to interact with the worker pool.
51
58
  */
52
59
  const createWorker = (builder, limit = 4) => {
53
60
  let workers = Array(limit)
@@ -60,13 +67,23 @@ const createWorker = (builder, limit = 4) => {
60
67
  const target = workers.find(({ resultResolver }) => !resultResolver);
61
68
  if (target) {
62
69
  target.resultResolver = Promise.withResolvers();
63
- if (!target.worker)
64
- target.worker = await init(builder());
70
+ if (!target.worker) {
71
+ const result = builder();
72
+ const worker = result instanceof node_worker_threads_1.Worker ? result : new node_worker_threads_1.Worker(result);
73
+ target.worker = await init(worker);
74
+ }
65
75
  return target;
66
76
  }
67
77
  await Promise.race(workers.map(({ resultResolver }) => resultResolver?.promise));
68
78
  }
69
79
  };
80
+ /**
81
+ * @method execute - Executes a method on a worker.
82
+ * @template K - The key of the method to execute.
83
+ * @param {K} name - The name of the method to execute.
84
+ * @param {...Parameters<T[K]>} value - The arguments to pass to the method.
85
+ * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.
86
+ */
70
87
  const execute = async (name, ...value) => {
71
88
  const target = await getResolver();
72
89
  const { resultResolver } = target;
@@ -80,12 +97,34 @@ const createWorker = (builder, limit = 4) => {
80
97
  });
81
98
  return resultResolver.promise;
82
99
  };
100
+ /**
101
+ * @method launchWorker - Launches all workers in the pool.
102
+ * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.
103
+ */
104
+ const launchWorker = async () => {
105
+ return Promise.all(workers.map(async (target) => {
106
+ if (!target.worker) {
107
+ const result = builder();
108
+ const worker = result instanceof node_worker_threads_1.Worker ? result : new node_worker_threads_1.Worker(result);
109
+ target.worker = await init(worker);
110
+ }
111
+ }));
112
+ };
113
+ /**
114
+ * @method waitAll - Waits for all workers to complete their tasks.
115
+ * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.
116
+ */
83
117
  const waitAll = async () => {
84
118
  while (workers.find(({ resultResolver }) => resultResolver)) {
85
119
  await Promise.all(workers.flatMap(({ resultResolver }) => resultResolver ? [resultResolver.promise] : []));
86
120
  }
87
121
  };
88
- const waitReady = async (retryTime = 0) => {
122
+ /**
123
+ * @method waitReady - Waits for the worker pool to be ready.
124
+ * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.
125
+ * @returns {Promise<void>} A promise that resolves when the worker pool is ready.
126
+ */
127
+ const waitReady = async (retryTime = 1) => {
89
128
  const p = Promise.withResolvers();
90
129
  emptyWaits.push(p);
91
130
  (async () => {
@@ -106,26 +145,33 @@ const createWorker = (builder, limit = 4) => {
106
145
  })();
107
146
  return p.promise;
108
147
  };
148
+ /**
149
+ * @method close - Terminates all workers in the pool.
150
+ */
109
151
  const close = () => {
110
152
  for (const { worker } of workers) {
111
153
  worker?.terminate();
112
154
  }
113
155
  };
156
+ /**
157
+ * @method setLimit - Sets a new limit for the number of concurrent workers.
158
+ * @param {number} limit - The new limit for the number of concurrent workers.
159
+ */
114
160
  const setLimit = (limit) => {
115
161
  workers.forEach((w) => w.worker?.terminate());
116
162
  workers = Array(limit)
117
163
  .fill(undefined)
118
164
  .map(() => ({}));
119
165
  };
120
- return { execute, waitAll, waitReady, close, setLimit };
166
+ return { execute, waitAll, waitReady, close, setLimit, launchWorker };
121
167
  };
122
168
  exports.createWorker = createWorker;
123
169
  /**
170
+ * Initializes a web worker with the provided worker process.
124
171
  *
125
- *
126
- * @template T
127
- * @param {T} WorkerProc
128
- * @return {*}
172
+ * @template T - The type of the worker process.
173
+ * @param {T} WorkerProc - The worker process to initialize.
174
+ * @returns {T} The initialized worker process.
129
175
  */
130
176
  const initWorker = (WorkerProc) => {
131
177
  const worker = node_worker_threads_1.parentPort;
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, type 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 * createWorker\n *\n * @template T\n * @param {() => Worker} builder\n * @param {number} [limit=0]\n * @return {*}\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker,\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) target.worker = await init(builder());\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\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 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 const waitReady = async (retryTime = 0) => {\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 const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\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 };\n};\n/**\n *\n *\n * @template T\n * @param {T} WorkerProc\n * @return {*}\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 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"]}
@@ -3,26 +3,34 @@ type WorkerType = {
3
3
  [key: string]: (...args: any) => any;
4
4
  };
5
5
  /**
6
- * createWorker
6
+ * Creates a worker pool with a specified limit of concurrent workers.
7
7
  *
8
- * @template T
9
- * @param {() => Worker} builder
10
- * @param {number} [limit=0]
11
- * @return {*}
8
+ * @template T - The type of the worker.
9
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
10
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
11
+ * @returns {{
12
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
13
+ * waitAll: () => Promise<void>,
14
+ * waitReady: (retryTime?: number) => Promise<void>,
15
+ * close: () => void,
16
+ * setLimit: (limit: number) => void,
17
+ * launchWorker: () => Promise<void[]>
18
+ * }} An object containing methods to interact with the worker pool.
12
19
  */
13
- export declare const createWorker: <T extends WorkerType>(builder: () => Worker | WorkerNode, limit?: number) => {
20
+ export declare const createWorker: <T extends WorkerType>(builder: () => Worker | WorkerNode | string | URL, limit?: number) => {
14
21
  execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>;
15
22
  waitAll: () => Promise<void>;
16
23
  waitReady: (retryTime?: number) => Promise<void>;
17
24
  close: () => void;
18
25
  setLimit: (limit: number) => void;
26
+ launchWorker: () => Promise<void[]>;
19
27
  };
20
28
  /**
29
+ * Initializes a web worker with the provided worker process.
21
30
  *
22
- *
23
- * @template T
24
- * @param {T} WorkerProc
25
- * @return {*}
31
+ * @template T - The type of the worker process.
32
+ * @param {T} WorkerProc - The worker process to initialize.
33
+ * @returns {T} The initialized worker process.
26
34
  */
27
35
  export declare const initWorker: <T extends WorkerType>(WorkerProc: T) => T;
28
36
  export {};
package/dist/esm/index.js CHANGED
@@ -39,12 +39,19 @@ const exec = (worker, name, ...value) => {
39
39
  });
40
40
  };
41
41
  /**
42
- * createWorker
42
+ * Creates a worker pool with a specified limit of concurrent workers.
43
43
  *
44
- * @template T
45
- * @param {() => Worker} builder
46
- * @param {number} [limit=0]
47
- * @return {*}
44
+ * @template T - The type of the worker.
45
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
46
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
47
+ * @returns {{
48
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
49
+ * waitAll: () => Promise<void>,
50
+ * waitReady: (retryTime?: number) => Promise<void>,
51
+ * close: () => void,
52
+ * setLimit: (limit: number) => void,
53
+ * launchWorker: () => Promise<void[]>
54
+ * }} An object containing methods to interact with the worker pool.
48
55
  */
49
56
  export const createWorker = (builder, limit = 4) => {
50
57
  let workers = Array(limit)
@@ -57,13 +64,25 @@ export const createWorker = (builder, limit = 4) => {
57
64
  const target = workers.find(({ resultResolver }) => !resultResolver);
58
65
  if (target) {
59
66
  target.resultResolver = Promise.withResolvers();
60
- if (!target.worker)
61
- target.worker = await init(builder());
67
+ if (!target.worker) {
68
+ const result = builder();
69
+ const worker = result instanceof Worker
70
+ ? result
71
+ : new Worker(result);
72
+ target.worker = await init(worker);
73
+ }
62
74
  return target;
63
75
  }
64
76
  await Promise.race(workers.map(({ resultResolver }) => resultResolver?.promise));
65
77
  }
66
78
  };
79
+ /**
80
+ * @method execute - Executes a method on a worker.
81
+ * @template K - The key of the method to execute.
82
+ * @param {K} name - The name of the method to execute.
83
+ * @param {...Parameters<T[K]>} value - The arguments to pass to the method.
84
+ * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.
85
+ */
67
86
  const execute = async (name, ...value) => {
68
87
  const target = await getResolver();
69
88
  const { resultResolver } = target;
@@ -77,11 +96,35 @@ export const createWorker = (builder, limit = 4) => {
77
96
  });
78
97
  return resultResolver.promise;
79
98
  };
99
+ /**
100
+ * @method launchWorker - Launches all workers in the pool.
101
+ * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.
102
+ */
103
+ const launchWorker = async () => {
104
+ return Promise.all(workers.map(async (target) => {
105
+ if (!target.worker) {
106
+ const result = builder();
107
+ const worker = result instanceof Worker
108
+ ? result
109
+ : new Worker(result);
110
+ target.worker = await init(worker);
111
+ }
112
+ }));
113
+ };
114
+ /**
115
+ * @method waitAll - Waits for all workers to complete their tasks.
116
+ * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.
117
+ */
80
118
  const waitAll = async () => {
81
119
  while (workers.find(({ resultResolver }) => resultResolver)) {
82
120
  await Promise.all(workers.flatMap(({ resultResolver }) => resultResolver ? [resultResolver.promise] : []));
83
121
  }
84
122
  };
123
+ /**
124
+ * @method waitReady - Waits for the worker pool to be ready.
125
+ * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.
126
+ * @returns {Promise<void>} A promise that resolves when the worker pool is ready.
127
+ */
85
128
  const waitReady = async (retryTime = 1) => {
86
129
  const p = Promise.withResolvers();
87
130
  emptyWaits.push(p);
@@ -103,25 +146,32 @@ export const createWorker = (builder, limit = 4) => {
103
146
  })();
104
147
  return p.promise;
105
148
  };
149
+ /**
150
+ * @method close - Terminates all workers in the pool.
151
+ */
106
152
  const close = () => {
107
153
  for (const { worker } of workers) {
108
154
  worker?.terminate();
109
155
  }
110
156
  };
157
+ /**
158
+ * @method setLimit - Sets a new limit for the number of concurrent workers.
159
+ * @param {number} limit - The new limit for the number of concurrent workers.
160
+ */
111
161
  const setLimit = (limit) => {
112
162
  workers.forEach((w) => w.worker?.terminate());
113
163
  workers = Array(limit)
114
164
  .fill(undefined)
115
165
  .map(() => ({}));
116
166
  };
117
- return { execute, waitAll, waitReady, close, setLimit };
167
+ return { execute, waitAll, waitReady, close, setLimit, launchWorker };
118
168
  };
119
169
  /**
170
+ * Initializes a web worker with the provided worker process.
120
171
  *
121
- *
122
- * @template T
123
- * @param {T} WorkerProc
124
- * @return {*}
172
+ * @template T - The type of the worker process.
173
+ * @param {T} WorkerProc - The worker process to initialize.
174
+ * @returns {T} The initialized worker process.
125
175
  */
126
176
  export const initWorker = (WorkerProc) => {
127
177
  const worker = self;
@@ -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 * createWorker\n *\n * @template T\n * @param {() => Worker} builder\n * @param {number} [limit=0]\n * @return {*}\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker | WorkerNode,\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) target.worker = await init(builder() as Worker);\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\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 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 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 const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\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 };\n};\n/**\n *\n *\n * @template T\n * @param {T} WorkerProc\n * @return {*}\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 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,28 +1,36 @@
1
- import { type Worker } from "node:worker_threads";
1
+ import { Worker } from "node:worker_threads";
2
2
  type WorkerType = {
3
3
  [key: string]: (...args: any) => any;
4
4
  };
5
5
  /**
6
- * createWorker
6
+ * Creates a worker pool with a specified limit of concurrent workers.
7
7
  *
8
- * @template T
9
- * @param {() => Worker} builder
10
- * @param {number} [limit=0]
11
- * @return {*}
8
+ * @template T - The type of the worker.
9
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
10
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
11
+ * @returns {{
12
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
13
+ * waitAll: () => Promise<void>,
14
+ * waitReady: (retryTime?: number) => Promise<void>,
15
+ * close: () => void,
16
+ * setLimit: (limit: number) => void,
17
+ * launchWorker: () => Promise<void[]>
18
+ * }} An object containing methods to interact with the worker pool.
12
19
  */
13
- export declare const createWorker: <T extends WorkerType>(builder: () => Worker, limit?: number) => {
20
+ export declare const createWorker: <T extends WorkerType>(builder: () => Worker | string | URL, limit?: number) => {
14
21
  execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>;
15
22
  waitAll: () => Promise<void>;
16
23
  waitReady: (retryTime?: number) => Promise<void>;
17
24
  close: () => void;
18
25
  setLimit: (limit: number) => void;
26
+ launchWorker: () => Promise<void[]>;
19
27
  };
20
28
  /**
29
+ * Initializes a web worker with the provided worker process.
21
30
  *
22
- *
23
- * @template T
24
- * @param {T} WorkerProc
25
- * @return {*}
31
+ * @template T - The type of the worker process.
32
+ * @param {T} WorkerProc - The worker process to initialize.
33
+ * @returns {T} The initialized worker process.
26
34
  */
27
35
  export declare const initWorker: <T extends WorkerType>(WorkerProc: T) => T;
28
36
  export {};
package/dist/esm/node.js CHANGED
@@ -1,4 +1,4 @@
1
- import { parentPort } from "node:worker_threads";
1
+ import { parentPort, Worker } from "node:worker_threads";
2
2
  const init = (worker) => {
3
3
  return new Promise((resolve) => {
4
4
  worker.once("message", () => {
@@ -39,12 +39,19 @@ const exec = (worker, name, ...value) => {
39
39
  });
40
40
  };
41
41
  /**
42
- * createWorker
42
+ * Creates a worker pool with a specified limit of concurrent workers.
43
43
  *
44
- * @template T
45
- * @param {() => Worker} builder
46
- * @param {number} [limit=0]
47
- * @return {*}
44
+ * @template T - The type of the worker.
45
+ * @param {() => Worker | WorkerNode} builder - A function that returns a new Worker or WorkerNode instance.
46
+ * @param {number} [limit=4] - The maximum number of concurrent workers.
47
+ * @returns {{
48
+ * execute: <K extends keyof T>(name: K, ...value: Parameters<T[K]>) => Promise<Awaited<ReturnType<T[K]>>>,
49
+ * waitAll: () => Promise<void>,
50
+ * waitReady: (retryTime?: number) => Promise<void>,
51
+ * close: () => void,
52
+ * setLimit: (limit: number) => void,
53
+ * launchWorker: () => Promise<void[]>
54
+ * }} An object containing methods to interact with the worker pool.
48
55
  */
49
56
  export const createWorker = (builder, limit = 4) => {
50
57
  let workers = Array(limit)
@@ -57,13 +64,23 @@ export const createWorker = (builder, limit = 4) => {
57
64
  const target = workers.find(({ resultResolver }) => !resultResolver);
58
65
  if (target) {
59
66
  target.resultResolver = Promise.withResolvers();
60
- if (!target.worker)
61
- target.worker = await init(builder());
67
+ if (!target.worker) {
68
+ const result = builder();
69
+ const worker = result instanceof Worker ? result : new Worker(result);
70
+ target.worker = await init(worker);
71
+ }
62
72
  return target;
63
73
  }
64
74
  await Promise.race(workers.map(({ resultResolver }) => resultResolver?.promise));
65
75
  }
66
76
  };
77
+ /**
78
+ * @method execute - Executes a method on a worker.
79
+ * @template K - The key of the method to execute.
80
+ * @param {K} name - The name of the method to execute.
81
+ * @param {...Parameters<T[K]>} value - The arguments to pass to the method.
82
+ * @returns {Promise<Awaited<ReturnType<T[K]>>>} A promise that resolves with the result of the method.
83
+ */
67
84
  const execute = async (name, ...value) => {
68
85
  const target = await getResolver();
69
86
  const { resultResolver } = target;
@@ -77,12 +94,34 @@ export const createWorker = (builder, limit = 4) => {
77
94
  });
78
95
  return resultResolver.promise;
79
96
  };
97
+ /**
98
+ * @method launchWorker - Launches all workers in the pool.
99
+ * @returns {Promise<void[]>} A promise that resolves when all workers have been launched.
100
+ */
101
+ const launchWorker = async () => {
102
+ return Promise.all(workers.map(async (target) => {
103
+ if (!target.worker) {
104
+ const result = builder();
105
+ const worker = result instanceof Worker ? result : new Worker(result);
106
+ target.worker = await init(worker);
107
+ }
108
+ }));
109
+ };
110
+ /**
111
+ * @method waitAll - Waits for all workers to complete their tasks.
112
+ * @returns {Promise<void>} A promise that resolves when all workers have completed their tasks.
113
+ */
80
114
  const waitAll = async () => {
81
115
  while (workers.find(({ resultResolver }) => resultResolver)) {
82
116
  await Promise.all(workers.flatMap(({ resultResolver }) => resultResolver ? [resultResolver.promise] : []));
83
117
  }
84
118
  };
85
- const waitReady = async (retryTime = 0) => {
119
+ /**
120
+ * @method waitReady - Waits for the worker pool to be ready.
121
+ * @param {number} [retryTime=1] - The time to wait between retries in milliseconds.
122
+ * @returns {Promise<void>} A promise that resolves when the worker pool is ready.
123
+ */
124
+ const waitReady = async (retryTime = 1) => {
86
125
  const p = Promise.withResolvers();
87
126
  emptyWaits.push(p);
88
127
  (async () => {
@@ -103,25 +142,32 @@ export const createWorker = (builder, limit = 4) => {
103
142
  })();
104
143
  return p.promise;
105
144
  };
145
+ /**
146
+ * @method close - Terminates all workers in the pool.
147
+ */
106
148
  const close = () => {
107
149
  for (const { worker } of workers) {
108
150
  worker?.terminate();
109
151
  }
110
152
  };
153
+ /**
154
+ * @method setLimit - Sets a new limit for the number of concurrent workers.
155
+ * @param {number} limit - The new limit for the number of concurrent workers.
156
+ */
111
157
  const setLimit = (limit) => {
112
158
  workers.forEach((w) => w.worker?.terminate());
113
159
  workers = Array(limit)
114
160
  .fill(undefined)
115
161
  .map(() => ({}));
116
162
  };
117
- return { execute, waitAll, waitReady, close, setLimit };
163
+ return { execute, waitAll, waitReady, close, setLimit, launchWorker };
118
164
  };
119
165
  /**
166
+ * Initializes a web worker with the provided worker process.
120
167
  *
121
- *
122
- * @template T
123
- * @param {T} WorkerProc
124
- * @return {*}
168
+ * @template T - The type of the worker process.
169
+ * @param {T} WorkerProc - The worker process to initialize.
170
+ * @returns {T} The initialized worker process.
125
171
  */
126
172
  export const initWorker = (WorkerProc) => {
127
173
  const worker = parentPort;
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { parentPort, type 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 * createWorker\n *\n * @template T\n * @param {() => Worker} builder\n * @param {number} [limit=0]\n * @return {*}\n */\nexport const createWorker = <T extends WorkerType>(\n builder: () => Worker,\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) target.worker = await init(builder());\n return target;\n }\n await Promise.race(\n workers.map(({ resultResolver }) => resultResolver?.promise)\n );\n }\n };\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 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 const waitReady = async (retryTime = 0) => {\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 const close = () => {\n for (const { worker } of workers) {\n worker?.terminate();\n }\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 };\n};\n/**\n *\n *\n * @template T\n * @param {T} WorkerProc\n * @return {*}\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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "worker-lib",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "main": "./dist/cjs/index.js",
5
5
  "types": "./dist/cjs/index.d.ts",
6
6
  "exports": {
@@ -48,9 +48,9 @@
48
48
  "build": "tsc && tsc --project ./tsconfig.esm.json && cpy esm dist"
49
49
  },
50
50
  "devDependencies": {
51
- "@types/node": "22.13.5",
51
+ "@types/node": "22.13.9",
52
52
  "cpy-cli": "5.0.0",
53
- "typescript": "^5.7.3"
53
+ "typescript": "^5.8.2"
54
54
  },
55
55
  "description": "Library for easy use of web-worker",
56
56
  "repository": {