} from './WorkerTypes.js'
import { randomizeDelay, sleep } from './WorkerUtils.js'
-export class WorkerSet extends WorkerAbstract<WorkerData> {
+export class WorkerSet<D extends WorkerData, R extends WorkerData> extends WorkerAbstract<D, R> {
public readonly emitter: EventEmitterAsyncResource | undefined
private readonly workerSet: Set<WorkerSetElement>
private started: boolean
this.emitter?.emit(WorkerSetEvents.stopped, this.info)
this.started = false
this.emitter?.emitDestroy()
- this.emitter?.removeAllListeners()
}
/** @inheritDoc */
- public async addElement (elementData: WorkerData): Promise<void> {
+ public async addElement (elementData: D): Promise<R> {
if (!this.started) {
throw new Error('Cannot add a WorkerSet element: not started')
}
const workerSetElement = await this.getWorkerSetElement()
+ const waitAddedWorkerElement = new Promise<R>((resolve, reject) => {
+ const messageHandler = (message: WorkerMessage<R>): void => {
+ if (message.event === WorkerMessageEvents.addedWorkerElement) {
+ ++workerSetElement.numberOfWorkerElements
+ resolve(message.data)
+ workerSetElement.worker.off('message', messageHandler)
+ } else if (message.event === WorkerMessageEvents.workerElementError) {
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
+ reject(message.data)
+ workerSetElement.worker.off('message', messageHandler)
+ }
+ }
+ workerSetElement.worker.on('message', messageHandler)
+ })
workerSetElement.worker.postMessage({
event: WorkerMessageEvents.addWorkerElement,
data: elementData
})
- ++workerSetElement.numberOfWorkerElements
+ const response = await waitAddedWorkerElement
// Add element sequentially to optimize memory at startup
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- if (this.workerOptions.elementStartDelay! > 0) {
+ if (this.workerOptions.elementAddDelay! > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- await sleep(randomizeDelay(this.workerOptions.elementStartDelay!))
+ await sleep(randomizeDelay(this.workerOptions.elementAddDelay!))
}
+ return response
}
/**
...this.workerOptions.poolOptions?.workerOptions
})
worker.on('message', this.workerOptions.poolOptions?.messageHandler ?? EMPTY_FUNCTION)
- worker.on('message', (message: WorkerMessage<WorkerData>) => {
+ worker.on('message', (message: WorkerMessage<R>) => {
if (message.event === WorkerMessageEvents.addedWorkerElement) {
this.emitter?.emit(WorkerSetEvents.elementAdded, this.info)
} else if (message.event === WorkerMessageEvents.workerElementError) {
this.addWorkerSetElement()
}
worker.unref()
- worker.terminate().catch(error => this.emitter?.emit(WorkerSetEvents.error, error))
+ worker.terminate().catch((error: unknown) => this.emitter?.emit(WorkerSetEvents.error, error))
})
worker.on('online', this.workerOptions.poolOptions?.onlineHandler ?? EMPTY_FUNCTION)
worker.on('exit', this.workerOptions.poolOptions?.exitHandler ?? EMPTY_FUNCTION)