Commit | Line | Data |
---|---|---|
6af9012e | 1 | import Configuration from '../utils/Configuration'; |
5fdab605 | 2 | import Constants from '../utils/Constants'; |
ad2f27c3 | 3 | import { Worker } from 'worker_threads'; |
ad3de6c4 | 4 | import WorkerData from '../types/WorkerData'; |
ad2f27c3 | 5 | import WorkerPool from './WorkerPool'; |
7dde0b73 | 6 | |
3f40bc9c | 7 | export default class Wrk { |
ad2f27c3 JB |
8 | private static wrkInstances: Wrk[]; |
9 | private workerScript: string; | |
10 | private workerData: WorkerData; | |
11 | private worker: Worker; | |
12 | private maxWorkerElements: number; | |
13 | private numWorkerElements: number; | |
6af9012e | 14 | |
7dde0b73 JB |
15 | /** |
16 | * Create a new `Wrk`. | |
17 | * | |
ad3de6c4 JB |
18 | * @param {string} workerScript |
19 | * @param {WorkerData} workerData | |
fdb38ec0 | 20 | * @param {number} maxWorkerElements |
7dde0b73 | 21 | */ |
ff70d2ed | 22 | constructor(workerScript: string, workerData: WorkerData, maxWorkerElements = 1) { |
ad2f27c3 JB |
23 | this.workerData = workerData; |
24 | this.workerScript = workerScript; | |
25 | this.maxWorkerElements = maxWorkerElements; | |
26 | this.numWorkerElements = 0; | |
7dde0b73 | 27 | if (Configuration.useWorkerPool()) { |
4fa59b8a | 28 | WorkerPool.maxConcurrentWorkers = Configuration.getWorkerPoolMaxSize(); |
7dde0b73 | 29 | } |
7dde0b73 JB |
30 | } |
31 | ||
6af9012e JB |
32 | /** |
33 | * | |
34 | * @return {Promise} | |
35 | * @public | |
36 | */ | |
3d2ff9e4 | 37 | async start(): Promise<Worker> { |
6af9012e | 38 | if (Configuration.useWorkerPool()) { |
ad2f27c3 | 39 | await this.startWorkerPool(); |
3d2ff9e4 | 40 | } else { |
ad2f27c3 | 41 | await this.startWorker(); |
6af9012e | 42 | } |
ad2f27c3 | 43 | return this.worker; |
3d2ff9e4 J |
44 | } |
45 | ||
5fdab605 | 46 | /** |
3d2ff9e4 | 47 | * |
5fdab605 | 48 | * @return {void} |
3d2ff9e4 J |
49 | * @public |
50 | */ | |
97ed5cec | 51 | addWorkerElement(workerData: WorkerData): void { |
97ed5cec | 52 | if (Configuration.useWorkerPool()) { |
ff70d2ed JB |
53 | throw Error('Cannot add Wrk element if the worker pool is enabled'); |
54 | } | |
ad2f27c3 | 55 | if (this.numWorkerElements >= this.maxWorkerElements) { |
ff70d2ed | 56 | throw Error('Cannot add Wrk element: max number of elements per worker reached'); |
97ed5cec | 57 | } |
ad2f27c3 JB |
58 | this.workerData = workerData; |
59 | this.worker.postMessage({ id: Constants.START_WORKER_ELEMENT, workerData: workerData }); | |
60 | this.numWorkerElements++; | |
4fa59b8a JB |
61 | } |
62 | ||
63 | /** | |
64 | * | |
65 | * @return {number} | |
66 | * @public | |
67 | */ | |
68 | public getWorkerPoolSize(): number { | |
69 | if (Configuration.useWorkerPool()) { | |
70 | return WorkerPool.getPoolSize(); | |
71 | } | |
6af9012e JB |
72 | } |
73 | ||
7dde0b73 JB |
74 | /** |
75 | * | |
76 | * @return {Promise} | |
77 | * @private | |
78 | */ | |
ad2f27c3 | 79 | private async startWorkerPool() { |
7dde0b73 | 80 | return new Promise((resolve, reject) => { |
ad2f27c3 | 81 | WorkerPool.acquire(this.workerScript, { workerData: this.workerData }, (err, worker) => { |
7dde0b73 JB |
82 | if (err) { |
83 | return reject(err); | |
84 | } | |
85 | worker.once('message', resolve); | |
86 | worker.once('error', reject); | |
ad2f27c3 | 87 | this.worker = worker; |
7dde0b73 JB |
88 | }); |
89 | }); | |
90 | } | |
91 | ||
92 | /** | |
93 | * | |
94 | * @return {Promise} | |
95 | * @private | |
96 | */ | |
ad2f27c3 | 97 | private async startWorker() { |
7dde0b73 | 98 | return new Promise((resolve, reject) => { |
ad2f27c3 | 99 | const worker = new Worker(this.workerScript, { workerData: this.workerData }); |
7dde0b73 JB |
100 | worker.on('message', resolve); |
101 | worker.on('error', reject); | |
102 | worker.on('exit', (code) => { | |
103 | if (code !== 0) { | |
4faad557 | 104 | reject(new Error(`Worker stopped with exit code ${code}`)); |
7dde0b73 JB |
105 | } |
106 | }); | |
ad2f27c3 JB |
107 | this.numWorkerElements++; |
108 | this.worker = worker; | |
7dde0b73 JB |
109 | }); |
110 | } | |
7dde0b73 | 111 | } |