@xylabs/threads 5.0.13 → 5.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index-browser.mjs +119 -209
- package/dist/browser/index-browser.mjs.map +1 -1
- package/dist/browser/master/implementation.browser.mjs +11 -36
- package/dist/browser/master/implementation.browser.mjs.map +1 -1
- package/dist/browser/master/index-browser.mjs +117 -201
- package/dist/browser/master/index-browser.mjs.map +1 -1
- package/dist/browser/master/pool-browser.mjs +53 -65
- package/dist/browser/master/pool-browser.mjs.map +1 -1
- package/dist/browser/worker/worker.browser.mjs +43 -79
- package/dist/browser/worker/worker.browser.mjs.map +1 -1
- package/dist/neutral/master/register.mjs +62 -121
- package/dist/neutral/master/register.mjs.map +1 -1
- package/dist/neutral/master/spawn.mjs +53 -106
- package/dist/neutral/master/spawn.mjs.map +1 -1
- package/dist/neutral/master/thread.mjs +0 -4
- package/dist/neutral/master/thread.mjs.map +1 -1
- package/dist/neutral/observable-promise.mjs +20 -27
- package/dist/neutral/observable-promise.mjs.map +1 -1
- package/dist/neutral/observable.mjs +3 -12
- package/dist/neutral/observable.mjs.map +1 -1
- package/dist/neutral/types/messages.mjs +4 -4
- package/dist/neutral/types/messages.mjs.map +1 -1
- package/dist/node/index-node.mjs +169 -293
- package/dist/node/index-node.mjs.map +1 -1
- package/dist/node/master/implementation.node.mjs +62 -121
- package/dist/node/master/implementation.node.mjs.map +1 -1
- package/dist/node/master/index-node.mjs +168 -286
- package/dist/node/master/index-node.mjs.map +1 -1
- package/dist/node/master/pool-node.mjs +115 -183
- package/dist/node/master/pool-node.mjs.map +1 -1
- package/dist/node/worker/worker.node.mjs +43 -80
- package/dist/node/worker/worker.node.mjs.map +1 -1
- package/package.json +3 -4
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
|
|
4
1
|
// src/master/pool-browser.ts
|
|
5
2
|
import DebugLogger from "debug";
|
|
6
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
multicast,
|
|
5
|
+
Observable,
|
|
6
|
+
Subject
|
|
7
|
+
} from "observable-fns";
|
|
7
8
|
|
|
8
9
|
// src/master/implementation.browser.ts
|
|
9
10
|
var defaultPoolSize = typeof navigator !== "undefined" && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4;
|
|
10
11
|
|
|
11
12
|
// src/master/pool-types.ts
|
|
12
|
-
var PoolEventType = /* @__PURE__ */
|
|
13
|
+
var PoolEventType = /* @__PURE__ */ ((PoolEventType2) => {
|
|
13
14
|
PoolEventType2["initialized"] = "initialized";
|
|
14
15
|
PoolEventType2["taskCanceled"] = "taskCanceled";
|
|
15
16
|
PoolEventType2["taskCompleted"] = "taskCompleted";
|
|
@@ -19,7 +20,7 @@ var PoolEventType = /* @__PURE__ */ function(PoolEventType2) {
|
|
|
19
20
|
PoolEventType2["taskStart"] = "taskStart";
|
|
20
21
|
PoolEventType2["terminated"] = "terminated";
|
|
21
22
|
return PoolEventType2;
|
|
22
|
-
}({});
|
|
23
|
+
})(PoolEventType || {});
|
|
23
24
|
|
|
24
25
|
// src/symbols.ts
|
|
25
26
|
var $errors = Symbol("thread.errors");
|
|
@@ -32,7 +33,6 @@ var $worker = Symbol("thread.worker");
|
|
|
32
33
|
function fail(message) {
|
|
33
34
|
throw new Error(message);
|
|
34
35
|
}
|
|
35
|
-
__name(fail, "fail");
|
|
36
36
|
var Thread = {
|
|
37
37
|
/** Return an observable that can be used to subscribe to all errors happening in the thread. */
|
|
38
38
|
errors(thread) {
|
|
@@ -57,33 +57,24 @@ function createArray(size) {
|
|
|
57
57
|
}
|
|
58
58
|
return array;
|
|
59
59
|
}
|
|
60
|
-
__name(createArray, "createArray");
|
|
61
60
|
function delay(ms) {
|
|
62
61
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
63
62
|
}
|
|
64
|
-
__name(delay, "delay");
|
|
65
63
|
function flatMap(array, mapper) {
|
|
66
|
-
return array.reduce((flattened, element) => [
|
|
67
|
-
...flattened,
|
|
68
|
-
...mapper(element)
|
|
69
|
-
], []);
|
|
64
|
+
return array.reduce((flattened, element) => [...flattened, ...mapper(element)], []);
|
|
70
65
|
}
|
|
71
|
-
__name(flatMap, "flatMap");
|
|
72
66
|
function slugify(text) {
|
|
73
67
|
return text.replaceAll(/\W/g, " ").trim().replaceAll(/\s+/g, "-");
|
|
74
68
|
}
|
|
75
|
-
__name(slugify, "slugify");
|
|
76
69
|
function spawnWorkers(spawnWorker, count) {
|
|
77
|
-
return createArray(count).map(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
return createArray(count).map(
|
|
71
|
+
() => ({
|
|
72
|
+
init: spawnWorker(),
|
|
73
|
+
runningTasks: []
|
|
74
|
+
})
|
|
75
|
+
);
|
|
81
76
|
}
|
|
82
|
-
|
|
83
|
-
var WorkerPool = class WorkerPool2 {
|
|
84
|
-
static {
|
|
85
|
-
__name(this, "WorkerPool");
|
|
86
|
-
}
|
|
77
|
+
var WorkerPool = class {
|
|
87
78
|
static EventType = PoolEventType;
|
|
88
79
|
debug;
|
|
89
80
|
eventObservable;
|
|
@@ -95,22 +86,23 @@ var WorkerPool = class WorkerPool2 {
|
|
|
95
86
|
nextTaskID = 1;
|
|
96
87
|
taskQueue = [];
|
|
97
88
|
constructor(spawnWorker, optionsOrSize) {
|
|
98
|
-
const options = typeof optionsOrSize === "number" ? {
|
|
99
|
-
size: optionsOrSize
|
|
100
|
-
} : optionsOrSize || {};
|
|
89
|
+
const options = typeof optionsOrSize === "number" ? { size: optionsOrSize } : optionsOrSize || {};
|
|
101
90
|
const { size = defaultPoolSize } = options;
|
|
102
91
|
this.debug = DebugLogger(`threads:pool:${slugify(options.name || String(nextPoolID++))}`);
|
|
103
92
|
this.options = options;
|
|
104
93
|
this.workers = spawnWorkers(spawnWorker, size);
|
|
105
94
|
this.eventObservable = multicast(Observable.from(this.eventSubject));
|
|
106
|
-
Promise.all(this.workers.map((worker) => worker.init)).then(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
95
|
+
Promise.all(this.workers.map((worker) => worker.init)).then(
|
|
96
|
+
() => this.eventSubject.next({
|
|
97
|
+
size: this.workers.length,
|
|
98
|
+
type: "initialized" /* initialized */
|
|
99
|
+
}),
|
|
100
|
+
(error) => {
|
|
101
|
+
this.debug("Error while initializing pool worker:", error);
|
|
102
|
+
this.eventSubject.error(error);
|
|
103
|
+
this.initErrors.push(error);
|
|
104
|
+
}
|
|
105
|
+
);
|
|
114
106
|
}
|
|
115
107
|
findIdlingWorker() {
|
|
116
108
|
const { concurrency = 1 } = this.options;
|
|
@@ -121,7 +113,7 @@ var WorkerPool = class WorkerPool2 {
|
|
|
121
113
|
this.debug(`Running task #${task.id} on worker #${workerID}...`);
|
|
122
114
|
this.eventSubject.next({
|
|
123
115
|
taskID: task.id,
|
|
124
|
-
type:
|
|
116
|
+
type: "taskStart" /* taskStart */,
|
|
125
117
|
workerID
|
|
126
118
|
});
|
|
127
119
|
try {
|
|
@@ -130,7 +122,7 @@ var WorkerPool = class WorkerPool2 {
|
|
|
130
122
|
this.eventSubject.next({
|
|
131
123
|
returnValue,
|
|
132
124
|
taskID: task.id,
|
|
133
|
-
type:
|
|
125
|
+
type: "taskCompleted" /* taskCompleted */,
|
|
134
126
|
workerID
|
|
135
127
|
});
|
|
136
128
|
} catch (ex) {
|
|
@@ -139,16 +131,16 @@ var WorkerPool = class WorkerPool2 {
|
|
|
139
131
|
this.eventSubject.next({
|
|
140
132
|
error,
|
|
141
133
|
taskID: task.id,
|
|
142
|
-
type:
|
|
134
|
+
type: "taskFailed" /* taskFailed */,
|
|
143
135
|
workerID
|
|
144
136
|
});
|
|
145
137
|
}
|
|
146
138
|
}
|
|
147
139
|
run(worker, task) {
|
|
148
140
|
const runPromise = (async () => {
|
|
149
|
-
const removeTaskFromWorkersRunningTasks =
|
|
141
|
+
const removeTaskFromWorkersRunningTasks = () => {
|
|
150
142
|
worker.runningTasks = worker.runningTasks.filter((someRunPromise) => someRunPromise !== runPromise);
|
|
151
|
-
}
|
|
143
|
+
};
|
|
152
144
|
await delay(0);
|
|
153
145
|
try {
|
|
154
146
|
await this.runPoolTask(worker, task);
|
|
@@ -168,9 +160,7 @@ var WorkerPool = class WorkerPool2 {
|
|
|
168
160
|
const nextTask = this.taskQueue.shift();
|
|
169
161
|
if (!nextTask) {
|
|
170
162
|
this.debug("Task queue is empty");
|
|
171
|
-
this.eventSubject.next({
|
|
172
|
-
type: PoolEventType.taskQueueDrained
|
|
173
|
-
});
|
|
163
|
+
this.eventSubject.next({ type: "taskQueueDrained" /* taskQueueDrained */ });
|
|
174
164
|
return;
|
|
175
165
|
}
|
|
176
166
|
this.run(availableWorker, nextTask);
|
|
@@ -178,13 +168,13 @@ var WorkerPool = class WorkerPool2 {
|
|
|
178
168
|
taskCompletion(taskID) {
|
|
179
169
|
return new Promise((resolve, reject) => {
|
|
180
170
|
const eventSubscription = this.events().subscribe((event) => {
|
|
181
|
-
if (event.type ===
|
|
171
|
+
if (event.type === "taskCompleted" /* taskCompleted */ && event.taskID === taskID) {
|
|
182
172
|
eventSubscription.unsubscribe();
|
|
183
173
|
resolve(event.returnValue);
|
|
184
|
-
} else if (event.type ===
|
|
174
|
+
} else if (event.type === "taskFailed" /* taskFailed */ && event.taskID === taskID) {
|
|
185
175
|
eventSubscription.unsubscribe();
|
|
186
176
|
reject(event.error);
|
|
187
|
-
} else if (event.type ===
|
|
177
|
+
} else if (event.type === "terminated" /* terminated */) {
|
|
188
178
|
eventSubscription.unsubscribe();
|
|
189
179
|
reject(new Error("Pool has been terminated before task was run."));
|
|
190
180
|
}
|
|
@@ -192,10 +182,10 @@ var WorkerPool = class WorkerPool2 {
|
|
|
192
182
|
});
|
|
193
183
|
}
|
|
194
184
|
async settled(allowResolvingImmediately = false) {
|
|
195
|
-
const getCurrentlyRunningTasks =
|
|
185
|
+
const getCurrentlyRunningTasks = () => flatMap(this.workers, (worker) => worker.runningTasks);
|
|
196
186
|
const taskFailures = [];
|
|
197
187
|
const failureSubscription = this.eventObservable.subscribe((event) => {
|
|
198
|
-
if (event.type ===
|
|
188
|
+
if (event.type === "taskFailed" /* taskFailed */) {
|
|
199
189
|
taskFailures.push(event.error);
|
|
200
190
|
}
|
|
201
191
|
});
|
|
@@ -210,11 +200,12 @@ var WorkerPool = class WorkerPool2 {
|
|
|
210
200
|
const subscription = this.eventObservable.subscribe({
|
|
211
201
|
error: reject,
|
|
212
202
|
next(event) {
|
|
213
|
-
if (event.type ===
|
|
203
|
+
if (event.type === "taskQueueDrained" /* taskQueueDrained */) {
|
|
214
204
|
subscription.unsubscribe();
|
|
215
205
|
resolve(void 0);
|
|
216
206
|
}
|
|
217
207
|
}
|
|
208
|
+
// make a pool-wide error reject the completed() result promise
|
|
218
209
|
});
|
|
219
210
|
});
|
|
220
211
|
await Promise.allSettled(getCurrentlyRunningTasks());
|
|
@@ -227,20 +218,18 @@ var WorkerPool = class WorkerPool2 {
|
|
|
227
218
|
const subscription = this.eventObservable.subscribe({
|
|
228
219
|
error: reject,
|
|
229
220
|
next(event) {
|
|
230
|
-
if (event.type ===
|
|
221
|
+
if (event.type === "taskQueueDrained" /* taskQueueDrained */) {
|
|
231
222
|
subscription.unsubscribe();
|
|
232
223
|
resolve(settlementPromise);
|
|
233
|
-
} else if (event.type ===
|
|
224
|
+
} else if (event.type === "taskFailed" /* taskFailed */) {
|
|
234
225
|
subscription.unsubscribe();
|
|
235
226
|
reject(event.error);
|
|
236
227
|
}
|
|
237
228
|
}
|
|
229
|
+
// make a pool-wide error reject the completed() result promise
|
|
238
230
|
});
|
|
239
231
|
});
|
|
240
|
-
const errors = await Promise.race([
|
|
241
|
-
settlementPromise,
|
|
242
|
-
earlyExitPromise
|
|
243
|
-
]);
|
|
232
|
+
const errors = await Promise.race([settlementPromise, earlyExitPromise]);
|
|
244
233
|
if (errors.length > 0) {
|
|
245
234
|
throw errors[0];
|
|
246
235
|
}
|
|
@@ -262,26 +251,28 @@ var WorkerPool = class WorkerPool2 {
|
|
|
262
251
|
this.debug(`Task #${taskID} errored:`, error);
|
|
263
252
|
});
|
|
264
253
|
const task = {
|
|
265
|
-
cancel:
|
|
254
|
+
cancel: () => {
|
|
266
255
|
if (!this.taskQueue.includes(task)) return;
|
|
267
256
|
this.taskQueue = this.taskQueue.filter((someTask) => someTask !== task);
|
|
268
257
|
this.eventSubject.next({
|
|
269
258
|
taskID: task.id,
|
|
270
|
-
type:
|
|
259
|
+
type: "taskCanceled" /* taskCanceled */
|
|
271
260
|
});
|
|
272
|
-
},
|
|
261
|
+
},
|
|
273
262
|
id: taskID,
|
|
274
263
|
run: taskFunction,
|
|
275
264
|
then: taskCompletion.then.bind(taskCompletion)
|
|
276
265
|
};
|
|
277
266
|
if (this.taskQueue.length >= maxQueuedJobs) {
|
|
278
|
-
throw new Error(
|
|
267
|
+
throw new Error(
|
|
268
|
+
"Maximum number of pool tasks queued. Refusing to queue another one.\nThis usually happens for one of two reasons: We are either at peak workload right now or some tasks just won't finish, thus blocking the pool."
|
|
269
|
+
);
|
|
279
270
|
}
|
|
280
271
|
this.debug(`Queueing task #${task.id}...`);
|
|
281
272
|
this.taskQueue.push(task);
|
|
282
273
|
this.eventSubject.next({
|
|
283
274
|
taskID: task.id,
|
|
284
|
-
type:
|
|
275
|
+
type: "taskQueued" /* taskQueued */
|
|
285
276
|
});
|
|
286
277
|
this.scheduleWork();
|
|
287
278
|
return task;
|
|
@@ -292,10 +283,8 @@ var WorkerPool = class WorkerPool2 {
|
|
|
292
283
|
await this.completed(true);
|
|
293
284
|
}
|
|
294
285
|
this.eventSubject.next({
|
|
295
|
-
remainingQueue: [
|
|
296
|
-
|
|
297
|
-
],
|
|
298
|
-
type: PoolEventType.terminated
|
|
286
|
+
remainingQueue: [...this.taskQueue],
|
|
287
|
+
type: "terminated" /* terminated */
|
|
299
288
|
});
|
|
300
289
|
this.eventSubject.complete();
|
|
301
290
|
await Promise.all(this.workers.map(async (worker) => Thread.terminate(await worker.init)));
|
|
@@ -304,7 +293,6 @@ var WorkerPool = class WorkerPool2 {
|
|
|
304
293
|
function PoolConstructor(spawnWorker, optionsOrSize) {
|
|
305
294
|
return new WorkerPool(spawnWorker, optionsOrSize);
|
|
306
295
|
}
|
|
307
|
-
__name(PoolConstructor, "PoolConstructor");
|
|
308
296
|
PoolConstructor.EventType = PoolEventType;
|
|
309
297
|
var Pool = PoolConstructor;
|
|
310
298
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/master/pool-browser.ts","../../../src/master/implementation.browser.ts","../../../src/master/pool-types.ts","../../../src/symbols.ts","../../../src/master/thread.ts"],"sourcesContent":["/* eslint-disable import-x/export */\n/* eslint-disable unicorn/no-thenable */\n\n/* eslint-disable @typescript-eslint/member-ordering */\n/* eslint-disable unicorn/no-array-reduce */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-namespace */\n\n/// <reference lib=\"esnext\" />\n\nimport DebugLogger from 'debug'\nimport {\n multicast, Observable, Subject,\n} from 'observable-fns'\n\nimport { defaultPoolSize } from './implementation.browser.ts'\nimport type {\n PoolEvent, QueuedTask, TaskRunFunction, WorkerDescriptor,\n} from './pool-types.ts'\nimport { PoolEventType } from './pool-types.ts'\nimport { Thread } from './thread.ts'\n\nexport declare namespace Pool {\n type Event<ThreadType extends Thread = any> = PoolEvent<ThreadType>\n type EventType = PoolEventType\n}\n\nlet nextPoolID = 1\n\nfunction createArray(size: number): number[] {\n const array: number[] = []\n for (let index = 0; index < size; index++) {\n array.push(index)\n }\n return array\n}\n\nfunction delay(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction flatMap<In, Out>(array: In[], mapper: (element: In) => Out[]): Out[] {\n return array.reduce<Out[]>((flattened, element) => [...flattened, ...mapper(element)], [])\n}\n\nfunction slugify(text: string) {\n return text.replaceAll(/\\W/g, ' ').trim().replaceAll(/\\s+/g, '-')\n}\n\nfunction spawnWorkers<ThreadType extends Thread>(spawnWorker: () => Promise<ThreadType>, count: number): Array<WorkerDescriptor<ThreadType>> {\n return createArray(count).map(\n (): WorkerDescriptor<ThreadType> => ({\n init: spawnWorker(),\n runningTasks: [],\n }),\n )\n}\n\n/**\n * Thread pool managing a set of worker threads.\n * Use it to queue tasks that are run on those threads with limited\n * concurrency.\n */\nexport interface Pool<ThreadType extends Thread> {\n /**\n * Returns a promise that resolves once the task queue is emptied.\n * Promise will be rejected if any task fails.\n *\n * @param allowResolvingImmediately Set to `true` to resolve immediately if task queue is currently empty.\n */\n completed(allowResolvingImmediately?: boolean): Promise<any>\n\n /**\n * Returns a promise that resolves once the task queue is emptied.\n * Failing tasks will not cause the promise to be rejected.\n *\n * @param allowResolvingImmediately Set to `true` to resolve immediately if task queue is currently empty.\n */\n settled(allowResolvingImmediately?: boolean): Promise<Error[]>\n\n /**\n * Returns an observable that yields pool events.\n */\n events(): Observable<PoolEvent<ThreadType>>\n\n /**\n * Queue a task and return a promise that resolves once the task has been dequeued,\n * started and finished.\n *\n * @param task An async function that takes a thread instance and invokes it.\n */\n queue<Return>(task: TaskRunFunction<ThreadType, Return>): QueuedTask<ThreadType, Return>\n\n /**\n * Terminate all pool threads.\n *\n * @param force Set to `true` to kill the thread even if it cannot be stopped gracefully.\n */\n terminate(force?: boolean): Promise<void>\n}\n\ninterface PoolOptions {\n /** Maximum no. of tasks to run on one worker thread at a time. Defaults to one. */\n concurrency?: number\n\n /** Maximum no. of jobs to be queued for execution before throwing an error. */\n maxQueuedJobs?: number\n\n /** Gives that pool a name to be used for debug logging, letting you distinguish between log output of different pools. */\n name?: string\n\n /** No. of worker threads to spawn and to be managed by the pool. */\n size?: number\n}\n\nclass WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {\n static EventType = PoolEventType\n\n private readonly debug: DebugLogger.Debugger\n private readonly eventObservable: Observable<PoolEvent<ThreadType>>\n private readonly options: PoolOptions\n private readonly workers: Array<WorkerDescriptor<ThreadType>>\n\n private readonly eventSubject = new Subject<PoolEvent<ThreadType>>()\n private initErrors: Error[] = []\n private isClosing = false\n private nextTaskID = 1\n private taskQueue: Array<QueuedTask<ThreadType, any>> = []\n\n constructor(spawnWorker: () => Promise<ThreadType>, optionsOrSize?: number | PoolOptions) {\n const options: PoolOptions = typeof optionsOrSize === 'number' ? { size: optionsOrSize } : optionsOrSize || {}\n\n const { size = defaultPoolSize } = options\n\n this.debug = DebugLogger(`threads:pool:${slugify(options.name || String(nextPoolID++))}`)\n this.options = options\n this.workers = spawnWorkers(spawnWorker, size)\n\n this.eventObservable = multicast(Observable.from(this.eventSubject))\n\n Promise.all(this.workers.map(worker => worker.init)).then(\n () =>\n this.eventSubject.next({\n size: this.workers.length,\n type: PoolEventType.initialized,\n }),\n (error) => {\n this.debug('Error while initializing pool worker:', error)\n this.eventSubject.error(error)\n this.initErrors.push(error)\n },\n )\n }\n\n private findIdlingWorker(): WorkerDescriptor<ThreadType> | undefined {\n const { concurrency = 1 } = this.options\n return this.workers.find(worker => worker.runningTasks.length < concurrency)\n }\n\n private async runPoolTask(worker: WorkerDescriptor<ThreadType>, task: QueuedTask<ThreadType, any>) {\n const workerID = this.workers.indexOf(worker) + 1\n\n this.debug(`Running task #${task.id} on worker #${workerID}...`)\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskStart,\n workerID,\n })\n\n try {\n const returnValue = await task.run(await worker.init)\n\n this.debug(`Task #${task.id} completed successfully`)\n this.eventSubject.next({\n returnValue,\n taskID: task.id,\n type: PoolEventType.taskCompleted,\n workerID,\n })\n } catch (ex) {\n const error = ex as Error\n this.debug(`Task #${task.id} failed`)\n this.eventSubject.next({\n error,\n taskID: task.id,\n type: PoolEventType.taskFailed,\n workerID,\n })\n }\n }\n\n private run(worker: WorkerDescriptor<ThreadType>, task: QueuedTask<ThreadType, any>) {\n const runPromise = (async () => {\n const removeTaskFromWorkersRunningTasks = () => {\n worker.runningTasks = worker.runningTasks.filter(someRunPromise => someRunPromise !== runPromise)\n }\n\n // Defer task execution by one tick to give handlers time to subscribe\n await delay(0)\n\n try {\n await this.runPoolTask(worker, task)\n } finally {\n removeTaskFromWorkersRunningTasks()\n\n if (!this.isClosing) {\n this.scheduleWork()\n }\n }\n })()\n\n worker.runningTasks.push(runPromise)\n }\n\n private scheduleWork() {\n this.debug('Attempt de-queueing a task in order to run it...')\n\n const availableWorker = this.findIdlingWorker()\n if (!availableWorker) return\n\n const nextTask = this.taskQueue.shift()\n if (!nextTask) {\n this.debug('Task queue is empty')\n this.eventSubject.next({ type: PoolEventType.taskQueueDrained })\n return\n }\n\n this.run(availableWorker, nextTask)\n }\n\n private taskCompletion(taskID: number) {\n return new Promise<any>((resolve, reject) => {\n const eventSubscription = this.events().subscribe((event) => {\n if (event.type === PoolEventType.taskCompleted && event.taskID === taskID) {\n eventSubscription.unsubscribe()\n resolve(event.returnValue)\n } else if (event.type === PoolEventType.taskFailed && event.taskID === taskID) {\n eventSubscription.unsubscribe()\n reject(event.error)\n } else if (event.type === PoolEventType.terminated) {\n eventSubscription.unsubscribe()\n reject(new Error('Pool has been terminated before task was run.'))\n }\n })\n })\n }\n\n async settled(allowResolvingImmediately: boolean = false): Promise<Error[]> {\n const getCurrentlyRunningTasks = () => flatMap(this.workers, worker => worker.runningTasks)\n\n const taskFailures: Error[] = []\n\n const failureSubscription = this.eventObservable.subscribe((event) => {\n if (event.type === PoolEventType.taskFailed) {\n taskFailures.push(event.error)\n }\n })\n\n if (this.initErrors.length > 0) {\n throw this.initErrors[0]\n }\n if (allowResolvingImmediately && this.taskQueue.length === 0) {\n await Promise.allSettled(getCurrentlyRunningTasks())\n return taskFailures\n }\n\n await new Promise<void>((resolve, reject) => {\n const subscription = this.eventObservable.subscribe({\n error: reject,\n next(event) {\n if (event.type === PoolEventType.taskQueueDrained) {\n subscription.unsubscribe()\n resolve(void 0)\n }\n }, // make a pool-wide error reject the completed() result promise\n })\n })\n\n await Promise.allSettled(getCurrentlyRunningTasks())\n failureSubscription.unsubscribe()\n\n return taskFailures\n }\n\n async completed(allowResolvingImmediately: boolean = false) {\n const settlementPromise = this.settled(allowResolvingImmediately)\n\n const earlyExitPromise = new Promise<Error[]>((resolve, reject) => {\n const subscription = this.eventObservable.subscribe({\n error: reject,\n next(event) {\n if (event.type === PoolEventType.taskQueueDrained) {\n subscription.unsubscribe()\n resolve(settlementPromise)\n } else if (event.type === PoolEventType.taskFailed) {\n subscription.unsubscribe()\n reject(event.error)\n }\n }, // make a pool-wide error reject the completed() result promise\n })\n })\n\n const errors = await Promise.race([settlementPromise, earlyExitPromise])\n\n if (errors.length > 0) {\n throw errors[0]\n }\n }\n\n events() {\n return this.eventObservable\n }\n\n queue(taskFunction: TaskRunFunction<ThreadType, any>) {\n const { maxQueuedJobs = Number.POSITIVE_INFINITY } = this.options\n\n if (this.isClosing) {\n throw new Error('Cannot schedule pool tasks after terminate() has been called.')\n }\n if (this.initErrors.length > 0) {\n throw this.initErrors[0]\n }\n\n const taskID = this.nextTaskID++\n const taskCompletion = this.taskCompletion(taskID)\n\n taskCompletion.catch((error) => {\n // Prevent unhandled rejections here as we assume the user will use\n // `pool.completed()`, `pool.settled()` or `task.catch()` to handle errors\n this.debug(`Task #${taskID} errored:`, error)\n })\n\n const task: QueuedTask<ThreadType, any> = {\n cancel: () => {\n if (!this.taskQueue.includes(task)) return\n this.taskQueue = this.taskQueue.filter(someTask => someTask !== task)\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskCanceled,\n })\n },\n id: taskID,\n run: taskFunction,\n then: taskCompletion.then.bind(taskCompletion),\n }\n\n if (this.taskQueue.length >= maxQueuedJobs) {\n throw new Error(\n 'Maximum number of pool tasks queued. Refusing to queue another one.\\n'\n + 'This usually happens for one of two reasons: We are either at peak '\n + \"workload right now or some tasks just won't finish, thus blocking the pool.\",\n )\n }\n\n this.debug(`Queueing task #${task.id}...`)\n this.taskQueue.push(task)\n\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskQueued,\n })\n\n this.scheduleWork()\n return task\n }\n\n async terminate(force?: boolean) {\n this.isClosing = true\n if (!force) {\n await this.completed(true)\n }\n this.eventSubject.next({\n remainingQueue: [...this.taskQueue],\n type: PoolEventType.terminated,\n })\n this.eventSubject.complete()\n await Promise.all(this.workers.map(async worker => Thread.terminate(await worker.init)))\n }\n}\n\n/**\n * Thread pool constructor. Creates a new pool and spawns its worker threads.\n */\nfunction PoolConstructor<ThreadType extends Thread>(spawnWorker: () => Promise<ThreadType>, optionsOrSize?: number | PoolOptions) {\n // The function exists only so we don't need to use `new` to create a pool (we still can, though).\n // If the Pool is a class or not is an implementation detail that should not concern the user.\n return new WorkerPool(spawnWorker, optionsOrSize)\n}\n\n;(PoolConstructor as any).EventType = PoolEventType\n\n/**\n * Thread pool constructor. Creates a new pool and spawns its worker threads.\n */\nexport const Pool = PoolConstructor as typeof PoolConstructor & { EventType: typeof PoolEventType }\n\nexport type { PoolEvent, QueuedTask } from './pool-types.ts'\nexport { PoolEventType } from './pool-types.ts'\nexport { Thread } from './thread.ts'\n","/* eslint-disable @stylistic/max-len */\n/* eslint-disable import-x/no-internal-modules */\n// tslint:disable max-classes-per-file\n\nimport type { ImplementationExport, ThreadsWorkerOptions } from '../types/master.ts'\nimport { getBundleURL } from './get-bundle-url.browser.ts'\n\nexport const defaultPoolSize = typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4\n\nconst isAbsoluteURL = (value: string) => /^[A-Za-z][\\d+.A-Za-z\\-]*:/.test(value)\n\nfunction createSourceBlobURL(code: string): string {\n const blob = new Blob([code], { type: 'application/javascript' })\n return URL.createObjectURL(blob)\n}\n\nfunction selectWorkerImplementation(): ImplementationExport {\n if (typeof Worker === 'undefined') {\n // Might happen on Safari, for instance\n // The idea is to only fail if the constructor is actually used\n return class NoWebWorker {\n constructor() {\n throw new Error(\n \"No web worker implementation available. You might have tried to spawn a worker within a worker in a browser that doesn't support workers in workers.\",\n )\n }\n } as unknown as ImplementationExport\n }\n\n class WebWorker extends Worker {\n constructor(url: string | URL, options?: ThreadsWorkerOptions) {\n if (typeof url === 'string' && options && options._baseURL) {\n url = new URL(url, options._baseURL)\n } else if (typeof url === 'string' && !isAbsoluteURL(url) && /^file:\\/\\//i.test(getBundleURL())) {\n url = new URL(url, getBundleURL().replace(/\\/[^/]+$/, '/'))\n if (options?.CORSWorkaround ?? true) {\n url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)\n }\n }\n if (\n typeof url === 'string'\n && isAbsoluteURL(url) // Create source code blob loading JS file via `importScripts()`\n // to circumvent worker CORS restrictions\n && (options?.CORSWorkaround ?? true)\n ) {\n url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)\n }\n super(url, options)\n }\n }\n\n class BlobWorker extends WebWorker {\n constructor(blob: Blob, options?: ThreadsWorkerOptions) {\n const url = globalThis.URL.createObjectURL(blob)\n super(url, options)\n }\n\n static fromText(source: string, options?: ThreadsWorkerOptions): WebWorker {\n const blob = new globalThis.Blob([source], { type: 'text/javascript' })\n return new BlobWorker(blob, options)\n }\n }\n\n return {\n blob: BlobWorker,\n default: WebWorker,\n }\n}\n\nlet implementation: ImplementationExport\n\nexport function getWorkerImplementation(): ImplementationExport {\n if (!implementation) {\n implementation = selectWorkerImplementation()\n }\n return implementation\n}\n\nexport function isWorkerRuntime() {\n const isWindowContext = typeof globalThis !== 'undefined' && typeof Window !== 'undefined' && globalThis instanceof Window\n return typeof globalThis !== 'undefined' && self['postMessage'] && !isWindowContext ? true : false\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/member-ordering */\nimport type { Thread } from './thread.ts'\n\n/** Pool event type. Specifies the type of each `PoolEvent`. */\nexport enum PoolEventType {\n initialized = 'initialized',\n taskCanceled = 'taskCanceled',\n taskCompleted = 'taskCompleted',\n taskFailed = 'taskFailed',\n taskQueued = 'taskQueued',\n taskQueueDrained = 'taskQueueDrained',\n taskStart = 'taskStart',\n terminated = 'terminated',\n}\n\nexport type TaskRunFunction<ThreadType extends Thread, Return> = (worker: ThreadType) => Promise<Return>\n\n/** Pool event. Subscribe to those events using `pool.events()`. Useful for debugging. */\nexport type PoolEvent<ThreadType extends Thread> =\n | {\n type: PoolEventType.initialized\n size: number\n }\n | {\n type: PoolEventType.taskQueued\n taskID: number\n }\n | {\n type: PoolEventType.taskQueueDrained\n }\n | {\n type: PoolEventType.taskStart\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskCompleted\n returnValue: any\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskFailed\n error: Error\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskCanceled\n taskID: number\n }\n | {\n type: PoolEventType.terminated\n remainingQueue: Array<QueuedTask<ThreadType, any>>\n }\n\nexport interface WorkerDescriptor<ThreadType extends Thread> {\n init: Promise<ThreadType>\n runningTasks: Array<Promise<any>>\n}\n\n/**\n * Task that has been `pool.queued()`-ed.\n */\nexport interface QueuedTask<ThreadType extends Thread, Return> {\n /** @private */\n id: number\n\n /** @private */\n run: TaskRunFunction<ThreadType, Return>\n\n /**\n * Queued tasks can be cancelled until the pool starts running them on a worker thread.\n */\n cancel(): void\n\n /**\n * `QueuedTask` is thenable, so you can `await` it.\n * Resolves when the task has successfully been executed. Rejects if the task fails.\n */\n then: Promise<Return>['then']\n}\n","export const $errors = Symbol('thread.errors')\nexport const $events = Symbol('thread.events')\nexport const $terminate = Symbol('thread.terminate')\nexport const $transferable = Symbol('thread.transferable')\nexport const $worker = Symbol('thread.worker')\n","/* eslint-disable import-x/no-internal-modules */\nimport type { Observable } from 'observable-fns'\n\nimport {\n $errors, $events, $terminate,\n} from '../symbols.ts'\nimport type { Thread as ThreadType, WorkerEvent } from '../types/master.ts'\n\nfunction fail(message: string): never {\n throw new Error(message)\n}\n\nexport type Thread = ThreadType\n\n/** Thread utility functions. Use them to manage or inspect a `spawn()`-ed thread. */\nexport const Thread = {\n /** Return an observable that can be used to subscribe to all errors happening in the thread. */\n errors<ThreadT extends ThreadType>(thread: ThreadT): Observable<Error> {\n return thread[$errors] || fail('Error observable not found. Make sure to pass a thread instance as returned by the spawn() promise.')\n },\n /** Return an observable that can be used to subscribe to internal events happening in the thread. Useful for debugging. */\n events<ThreadT extends ThreadType>(thread: ThreadT): Observable<WorkerEvent> {\n return thread[$events] || fail('Events observable not found. Make sure to pass a thread instance as returned by the spawn() promise.')\n },\n /** Terminate a thread. Remember to terminate every thread when you are done using it. */\n terminate<ThreadT extends ThreadType>(thread: ThreadT) {\n return thread[$terminate]()\n },\n}\n"],"mappings":"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","names":["DebugLogger","multicast","Observable","Subject","defaultPoolSize","navigator","hardwareConcurrency","PoolEventType","$errors","Symbol","$events","$terminate","$transferable","$worker","fail","message","Error","Thread","errors","thread","$errors","events","$events","terminate","$terminate","nextPoolID","createArray","size","array","index","push","delay","ms","Promise","resolve","setTimeout","flatMap","mapper","reduce","flattened","element","slugify","text","replaceAll","trim","spawnWorkers","spawnWorker","count","map","init","runningTasks","WorkerPool","EventType","PoolEventType","debug","eventObservable","options","workers","eventSubject","Subject","initErrors","isClosing","nextTaskID","taskQueue","optionsOrSize","defaultPoolSize","DebugLogger","name","String","multicast","Observable","from","all","worker","then","next","length","type","initialized","error","findIdlingWorker","concurrency","find","runPoolTask","task","workerID","indexOf","id","taskID","taskStart","returnValue","run","taskCompleted","ex","taskFailed","runPromise","removeTaskFromWorkersRunningTasks","filter","someRunPromise","scheduleWork","availableWorker","nextTask","shift","taskQueueDrained","taskCompletion","reject","eventSubscription","events","subscribe","event","unsubscribe","terminated","Error","settled","allowResolvingImmediately","getCurrentlyRunningTasks","taskFailures","failureSubscription","allSettled","subscription","completed","settlementPromise","earlyExitPromise","errors","race","queue","taskFunction","maxQueuedJobs","Number","POSITIVE_INFINITY","catch","cancel","includes","someTask","taskCanceled","bind","taskQueued","terminate","force","remainingQueue","complete","Thread","PoolConstructor","Pool"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/master/pool-browser.ts","../../../src/master/implementation.browser.ts","../../../src/master/pool-types.ts","../../../src/symbols.ts","../../../src/master/thread.ts"],"sourcesContent":["/* eslint-disable import-x/export */\n/* eslint-disable unicorn/no-thenable */\n\n/* eslint-disable @typescript-eslint/member-ordering */\n/* eslint-disable unicorn/no-array-reduce */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-namespace */\n\n/// <reference lib=\"esnext\" />\n\nimport DebugLogger from 'debug'\nimport {\n multicast, Observable, Subject,\n} from 'observable-fns'\n\nimport { defaultPoolSize } from './implementation.browser.ts'\nimport type {\n PoolEvent, QueuedTask, TaskRunFunction, WorkerDescriptor,\n} from './pool-types.ts'\nimport { PoolEventType } from './pool-types.ts'\nimport { Thread } from './thread.ts'\n\nexport declare namespace Pool {\n type Event<ThreadType extends Thread = any> = PoolEvent<ThreadType>\n type EventType = PoolEventType\n}\n\nlet nextPoolID = 1\n\nfunction createArray(size: number): number[] {\n const array: number[] = []\n for (let index = 0; index < size; index++) {\n array.push(index)\n }\n return array\n}\n\nfunction delay(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction flatMap<In, Out>(array: In[], mapper: (element: In) => Out[]): Out[] {\n return array.reduce<Out[]>((flattened, element) => [...flattened, ...mapper(element)], [])\n}\n\nfunction slugify(text: string) {\n return text.replaceAll(/\\W/g, ' ').trim().replaceAll(/\\s+/g, '-')\n}\n\nfunction spawnWorkers<ThreadType extends Thread>(spawnWorker: () => Promise<ThreadType>, count: number): Array<WorkerDescriptor<ThreadType>> {\n return createArray(count).map(\n (): WorkerDescriptor<ThreadType> => ({\n init: spawnWorker(),\n runningTasks: [],\n }),\n )\n}\n\n/**\n * Thread pool managing a set of worker threads.\n * Use it to queue tasks that are run on those threads with limited\n * concurrency.\n */\nexport interface Pool<ThreadType extends Thread> {\n /**\n * Returns a promise that resolves once the task queue is emptied.\n * Promise will be rejected if any task fails.\n *\n * @param allowResolvingImmediately Set to `true` to resolve immediately if task queue is currently empty.\n */\n completed(allowResolvingImmediately?: boolean): Promise<any>\n\n /**\n * Returns a promise that resolves once the task queue is emptied.\n * Failing tasks will not cause the promise to be rejected.\n *\n * @param allowResolvingImmediately Set to `true` to resolve immediately if task queue is currently empty.\n */\n settled(allowResolvingImmediately?: boolean): Promise<Error[]>\n\n /**\n * Returns an observable that yields pool events.\n */\n events(): Observable<PoolEvent<ThreadType>>\n\n /**\n * Queue a task and return a promise that resolves once the task has been dequeued,\n * started and finished.\n *\n * @param task An async function that takes a thread instance and invokes it.\n */\n queue<Return>(task: TaskRunFunction<ThreadType, Return>): QueuedTask<ThreadType, Return>\n\n /**\n * Terminate all pool threads.\n *\n * @param force Set to `true` to kill the thread even if it cannot be stopped gracefully.\n */\n terminate(force?: boolean): Promise<void>\n}\n\ninterface PoolOptions {\n /** Maximum no. of tasks to run on one worker thread at a time. Defaults to one. */\n concurrency?: number\n\n /** Maximum no. of jobs to be queued for execution before throwing an error. */\n maxQueuedJobs?: number\n\n /** Gives that pool a name to be used for debug logging, letting you distinguish between log output of different pools. */\n name?: string\n\n /** No. of worker threads to spawn and to be managed by the pool. */\n size?: number\n}\n\nclass WorkerPool<ThreadType extends Thread> implements Pool<ThreadType> {\n static EventType = PoolEventType\n\n private readonly debug: DebugLogger.Debugger\n private readonly eventObservable: Observable<PoolEvent<ThreadType>>\n private readonly options: PoolOptions\n private readonly workers: Array<WorkerDescriptor<ThreadType>>\n\n private readonly eventSubject = new Subject<PoolEvent<ThreadType>>()\n private initErrors: Error[] = []\n private isClosing = false\n private nextTaskID = 1\n private taskQueue: Array<QueuedTask<ThreadType, any>> = []\n\n constructor(spawnWorker: () => Promise<ThreadType>, optionsOrSize?: number | PoolOptions) {\n const options: PoolOptions = typeof optionsOrSize === 'number' ? { size: optionsOrSize } : optionsOrSize || {}\n\n const { size = defaultPoolSize } = options\n\n this.debug = DebugLogger(`threads:pool:${slugify(options.name || String(nextPoolID++))}`)\n this.options = options\n this.workers = spawnWorkers(spawnWorker, size)\n\n this.eventObservable = multicast(Observable.from(this.eventSubject))\n\n Promise.all(this.workers.map(worker => worker.init)).then(\n () =>\n this.eventSubject.next({\n size: this.workers.length,\n type: PoolEventType.initialized,\n }),\n (error) => {\n this.debug('Error while initializing pool worker:', error)\n this.eventSubject.error(error)\n this.initErrors.push(error)\n },\n )\n }\n\n private findIdlingWorker(): WorkerDescriptor<ThreadType> | undefined {\n const { concurrency = 1 } = this.options\n return this.workers.find(worker => worker.runningTasks.length < concurrency)\n }\n\n private async runPoolTask(worker: WorkerDescriptor<ThreadType>, task: QueuedTask<ThreadType, any>) {\n const workerID = this.workers.indexOf(worker) + 1\n\n this.debug(`Running task #${task.id} on worker #${workerID}...`)\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskStart,\n workerID,\n })\n\n try {\n const returnValue = await task.run(await worker.init)\n\n this.debug(`Task #${task.id} completed successfully`)\n this.eventSubject.next({\n returnValue,\n taskID: task.id,\n type: PoolEventType.taskCompleted,\n workerID,\n })\n } catch (ex) {\n const error = ex as Error\n this.debug(`Task #${task.id} failed`)\n this.eventSubject.next({\n error,\n taskID: task.id,\n type: PoolEventType.taskFailed,\n workerID,\n })\n }\n }\n\n private run(worker: WorkerDescriptor<ThreadType>, task: QueuedTask<ThreadType, any>) {\n const runPromise = (async () => {\n const removeTaskFromWorkersRunningTasks = () => {\n worker.runningTasks = worker.runningTasks.filter(someRunPromise => someRunPromise !== runPromise)\n }\n\n // Defer task execution by one tick to give handlers time to subscribe\n await delay(0)\n\n try {\n await this.runPoolTask(worker, task)\n } finally {\n removeTaskFromWorkersRunningTasks()\n\n if (!this.isClosing) {\n this.scheduleWork()\n }\n }\n })()\n\n worker.runningTasks.push(runPromise)\n }\n\n private scheduleWork() {\n this.debug('Attempt de-queueing a task in order to run it...')\n\n const availableWorker = this.findIdlingWorker()\n if (!availableWorker) return\n\n const nextTask = this.taskQueue.shift()\n if (!nextTask) {\n this.debug('Task queue is empty')\n this.eventSubject.next({ type: PoolEventType.taskQueueDrained })\n return\n }\n\n this.run(availableWorker, nextTask)\n }\n\n private taskCompletion(taskID: number) {\n return new Promise<any>((resolve, reject) => {\n const eventSubscription = this.events().subscribe((event) => {\n if (event.type === PoolEventType.taskCompleted && event.taskID === taskID) {\n eventSubscription.unsubscribe()\n resolve(event.returnValue)\n } else if (event.type === PoolEventType.taskFailed && event.taskID === taskID) {\n eventSubscription.unsubscribe()\n reject(event.error)\n } else if (event.type === PoolEventType.terminated) {\n eventSubscription.unsubscribe()\n reject(new Error('Pool has been terminated before task was run.'))\n }\n })\n })\n }\n\n async settled(allowResolvingImmediately: boolean = false): Promise<Error[]> {\n const getCurrentlyRunningTasks = () => flatMap(this.workers, worker => worker.runningTasks)\n\n const taskFailures: Error[] = []\n\n const failureSubscription = this.eventObservable.subscribe((event) => {\n if (event.type === PoolEventType.taskFailed) {\n taskFailures.push(event.error)\n }\n })\n\n if (this.initErrors.length > 0) {\n throw this.initErrors[0]\n }\n if (allowResolvingImmediately && this.taskQueue.length === 0) {\n await Promise.allSettled(getCurrentlyRunningTasks())\n return taskFailures\n }\n\n await new Promise<void>((resolve, reject) => {\n const subscription = this.eventObservable.subscribe({\n error: reject,\n next(event) {\n if (event.type === PoolEventType.taskQueueDrained) {\n subscription.unsubscribe()\n resolve(void 0)\n }\n }, // make a pool-wide error reject the completed() result promise\n })\n })\n\n await Promise.allSettled(getCurrentlyRunningTasks())\n failureSubscription.unsubscribe()\n\n return taskFailures\n }\n\n async completed(allowResolvingImmediately: boolean = false) {\n const settlementPromise = this.settled(allowResolvingImmediately)\n\n const earlyExitPromise = new Promise<Error[]>((resolve, reject) => {\n const subscription = this.eventObservable.subscribe({\n error: reject,\n next(event) {\n if (event.type === PoolEventType.taskQueueDrained) {\n subscription.unsubscribe()\n resolve(settlementPromise)\n } else if (event.type === PoolEventType.taskFailed) {\n subscription.unsubscribe()\n reject(event.error)\n }\n }, // make a pool-wide error reject the completed() result promise\n })\n })\n\n const errors = await Promise.race([settlementPromise, earlyExitPromise])\n\n if (errors.length > 0) {\n throw errors[0]\n }\n }\n\n events() {\n return this.eventObservable\n }\n\n queue(taskFunction: TaskRunFunction<ThreadType, any>) {\n const { maxQueuedJobs = Number.POSITIVE_INFINITY } = this.options\n\n if (this.isClosing) {\n throw new Error('Cannot schedule pool tasks after terminate() has been called.')\n }\n if (this.initErrors.length > 0) {\n throw this.initErrors[0]\n }\n\n const taskID = this.nextTaskID++\n const taskCompletion = this.taskCompletion(taskID)\n\n taskCompletion.catch((error) => {\n // Prevent unhandled rejections here as we assume the user will use\n // `pool.completed()`, `pool.settled()` or `task.catch()` to handle errors\n this.debug(`Task #${taskID} errored:`, error)\n })\n\n const task: QueuedTask<ThreadType, any> = {\n cancel: () => {\n if (!this.taskQueue.includes(task)) return\n this.taskQueue = this.taskQueue.filter(someTask => someTask !== task)\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskCanceled,\n })\n },\n id: taskID,\n run: taskFunction,\n then: taskCompletion.then.bind(taskCompletion),\n }\n\n if (this.taskQueue.length >= maxQueuedJobs) {\n throw new Error(\n 'Maximum number of pool tasks queued. Refusing to queue another one.\\n'\n + 'This usually happens for one of two reasons: We are either at peak '\n + \"workload right now or some tasks just won't finish, thus blocking the pool.\",\n )\n }\n\n this.debug(`Queueing task #${task.id}...`)\n this.taskQueue.push(task)\n\n this.eventSubject.next({\n taskID: task.id,\n type: PoolEventType.taskQueued,\n })\n\n this.scheduleWork()\n return task\n }\n\n async terminate(force?: boolean) {\n this.isClosing = true\n if (!force) {\n await this.completed(true)\n }\n this.eventSubject.next({\n remainingQueue: [...this.taskQueue],\n type: PoolEventType.terminated,\n })\n this.eventSubject.complete()\n await Promise.all(this.workers.map(async worker => Thread.terminate(await worker.init)))\n }\n}\n\n/**\n * Thread pool constructor. Creates a new pool and spawns its worker threads.\n */\nfunction PoolConstructor<ThreadType extends Thread>(spawnWorker: () => Promise<ThreadType>, optionsOrSize?: number | PoolOptions) {\n // The function exists only so we don't need to use `new` to create a pool (we still can, though).\n // If the Pool is a class or not is an implementation detail that should not concern the user.\n return new WorkerPool(spawnWorker, optionsOrSize)\n}\n\n;(PoolConstructor as any).EventType = PoolEventType\n\n/**\n * Thread pool constructor. Creates a new pool and spawns its worker threads.\n */\nexport const Pool = PoolConstructor as typeof PoolConstructor & { EventType: typeof PoolEventType }\n\nexport type { PoolEvent, QueuedTask } from './pool-types.ts'\nexport { PoolEventType } from './pool-types.ts'\nexport { Thread } from './thread.ts'\n","/* eslint-disable @stylistic/max-len */\n/* eslint-disable import-x/no-internal-modules */\n// tslint:disable max-classes-per-file\n\nimport type { ImplementationExport, ThreadsWorkerOptions } from '../types/master.ts'\nimport { getBundleURL } from './get-bundle-url.browser.ts'\n\nexport const defaultPoolSize = typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4\n\nconst isAbsoluteURL = (value: string) => /^[A-Za-z][\\d+.A-Za-z\\-]*:/.test(value)\n\nfunction createSourceBlobURL(code: string): string {\n const blob = new Blob([code], { type: 'application/javascript' })\n return URL.createObjectURL(blob)\n}\n\nfunction selectWorkerImplementation(): ImplementationExport {\n if (typeof Worker === 'undefined') {\n // Might happen on Safari, for instance\n // The idea is to only fail if the constructor is actually used\n return class NoWebWorker {\n constructor() {\n throw new Error(\n \"No web worker implementation available. You might have tried to spawn a worker within a worker in a browser that doesn't support workers in workers.\",\n )\n }\n } as unknown as ImplementationExport\n }\n\n class WebWorker extends Worker {\n constructor(url: string | URL, options?: ThreadsWorkerOptions) {\n if (typeof url === 'string' && options && options._baseURL) {\n url = new URL(url, options._baseURL)\n } else if (typeof url === 'string' && !isAbsoluteURL(url) && /^file:\\/\\//i.test(getBundleURL())) {\n url = new URL(url, getBundleURL().replace(/\\/[^/]+$/, '/'))\n if (options?.CORSWorkaround ?? true) {\n url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)\n }\n }\n if (\n typeof url === 'string'\n && isAbsoluteURL(url) // Create source code blob loading JS file via `importScripts()`\n // to circumvent worker CORS restrictions\n && (options?.CORSWorkaround ?? true)\n ) {\n url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`)\n }\n super(url, options)\n }\n }\n\n class BlobWorker extends WebWorker {\n constructor(blob: Blob, options?: ThreadsWorkerOptions) {\n const url = globalThis.URL.createObjectURL(blob)\n super(url, options)\n }\n\n static fromText(source: string, options?: ThreadsWorkerOptions): WebWorker {\n const blob = new globalThis.Blob([source], { type: 'text/javascript' })\n return new BlobWorker(blob, options)\n }\n }\n\n return {\n blob: BlobWorker,\n default: WebWorker,\n }\n}\n\nlet implementation: ImplementationExport\n\nexport function getWorkerImplementation(): ImplementationExport {\n if (!implementation) {\n implementation = selectWorkerImplementation()\n }\n return implementation\n}\n\nexport function isWorkerRuntime() {\n const isWindowContext = typeof globalThis !== 'undefined' && typeof Window !== 'undefined' && globalThis instanceof Window\n return typeof globalThis !== 'undefined' && self['postMessage'] && !isWindowContext ? true : false\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/member-ordering */\nimport type { Thread } from './thread.ts'\n\n/** Pool event type. Specifies the type of each `PoolEvent`. */\nexport enum PoolEventType {\n initialized = 'initialized',\n taskCanceled = 'taskCanceled',\n taskCompleted = 'taskCompleted',\n taskFailed = 'taskFailed',\n taskQueued = 'taskQueued',\n taskQueueDrained = 'taskQueueDrained',\n taskStart = 'taskStart',\n terminated = 'terminated',\n}\n\nexport type TaskRunFunction<ThreadType extends Thread, Return> = (worker: ThreadType) => Promise<Return>\n\n/** Pool event. Subscribe to those events using `pool.events()`. Useful for debugging. */\nexport type PoolEvent<ThreadType extends Thread> =\n | {\n type: PoolEventType.initialized\n size: number\n }\n | {\n type: PoolEventType.taskQueued\n taskID: number\n }\n | {\n type: PoolEventType.taskQueueDrained\n }\n | {\n type: PoolEventType.taskStart\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskCompleted\n returnValue: any\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskFailed\n error: Error\n taskID: number\n workerID: number\n }\n | {\n type: PoolEventType.taskCanceled\n taskID: number\n }\n | {\n type: PoolEventType.terminated\n remainingQueue: Array<QueuedTask<ThreadType, any>>\n }\n\nexport interface WorkerDescriptor<ThreadType extends Thread> {\n init: Promise<ThreadType>\n runningTasks: Array<Promise<any>>\n}\n\n/**\n * Task that has been `pool.queued()`-ed.\n */\nexport interface QueuedTask<ThreadType extends Thread, Return> {\n /** @private */\n id: number\n\n /** @private */\n run: TaskRunFunction<ThreadType, Return>\n\n /**\n * Queued tasks can be cancelled until the pool starts running them on a worker thread.\n */\n cancel(): void\n\n /**\n * `QueuedTask` is thenable, so you can `await` it.\n * Resolves when the task has successfully been executed. Rejects if the task fails.\n */\n then: Promise<Return>['then']\n}\n","export const $errors = Symbol('thread.errors')\nexport const $events = Symbol('thread.events')\nexport const $terminate = Symbol('thread.terminate')\nexport const $transferable = Symbol('thread.transferable')\nexport const $worker = Symbol('thread.worker')\n","/* eslint-disable import-x/no-internal-modules */\nimport type { Observable } from 'observable-fns'\n\nimport {\n $errors, $events, $terminate,\n} from '../symbols.ts'\nimport type { Thread as ThreadType, WorkerEvent } from '../types/master.ts'\n\nfunction fail(message: string): never {\n throw new Error(message)\n}\n\nexport type Thread = ThreadType\n\n/** Thread utility functions. Use them to manage or inspect a `spawn()`-ed thread. */\nexport const Thread = {\n /** Return an observable that can be used to subscribe to all errors happening in the thread. */\n errors<ThreadT extends ThreadType>(thread: ThreadT): Observable<Error> {\n return thread[$errors] || fail('Error observable not found. Make sure to pass a thread instance as returned by the spawn() promise.')\n },\n /** Return an observable that can be used to subscribe to internal events happening in the thread. Useful for debugging. */\n events<ThreadT extends ThreadType>(thread: ThreadT): Observable<WorkerEvent> {\n return thread[$events] || fail('Events observable not found. Make sure to pass a thread instance as returned by the spawn() promise.')\n },\n /** Terminate a thread. Remember to terminate every thread when you are done using it. */\n terminate<ThreadT extends ThreadType>(thread: ThreadT) {\n return thread[$terminate]()\n },\n}\n"],"mappings":"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","names":["PoolEventType"]}
|