)
}
+ protected async sendKillMessageToWorker (
+ workerNodeKey: number,
+ workerId: number
+ ): Promise<void> {
+ const waitForKillResponse = new Promise<void>((resolve, reject) => {
+ this.registerWorkerMessageListener(workerNodeKey, (message) => {
+ if (message.kill === 'success') {
+ resolve()
+ } else if (message.kill === 'failure') {
+ reject(new Error('Worker kill message handling failed'))
+ }
+ })
+ })
+ this.sendToWorker(workerNodeKey, { kill: true, workerId })
+ await waitForKillResponse
+ }
+
/**
* Terminates the worker node given its worker node key.
*
// Kill message received from worker
if (
isKillBehavior(KillBehaviors.HARD, message.kill) ||
- (message.kill != null &&
+ (isKillBehavior(KillBehaviors.SOFT, message.kill) &&
((this.opts.enableTasksQueue === false &&
workerUsage.tasks.executing === 0) ||
(this.opts.enableTasksQueue === true &&
worker.on('disconnect', () => {
worker.kill()
})
- this.sendToWorker(workerNodeKey, { kill: true, workerId: worker.id })
+ await this.sendKillMessageToWorker(workerNodeKey, worker.id)
worker.disconnect()
await waitWorkerExit
}
resolve()
})
})
- this.sendToWorker(workerNodeKey, { kill: true, workerId: worker.threadId })
+ await this.sendKillMessageToWorker(workerNodeKey, worker.threadId)
workerNode.closeChannel()
await worker.terminate()
await waitWorkerExit
/**
* Kill code.
*/
- readonly kill?: KillBehavior | true
+ readonly kill?: KillBehavior | true | 'success' | 'failure'
/**
* Task error.
*/
this.stopCheckActive()
if (isAsyncFunction(this.opts.killHandler)) {
(this.opts.killHandler?.() as Promise<void>)
- .then(() => this.emitDestroy())
+ .then(() => {
+ this.sendToMainWorker({ kill: 'success', workerId: this.id })
+ return null
+ })
+ .catch(() => {
+ this.sendToMainWorker({ kill: 'failure', workerId: this.id })
+ })
+ .finally(() => {
+ this.emitDestroy()
+ })
.catch(EMPTY_FUNCTION)
} else {
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
- this.opts.killHandler?.() as void
- this.emitDestroy()
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
+ this.opts.killHandler?.() as void
+ this.sendToMainWorker({ kill: 'success', workerId: this.id })
+ } catch (error) {
+ this.sendToMainWorker({ kill: 'failure', workerId: this.id })
+ } finally {
+ this.emitDestroy()
+ }
}
}
killHandler: sinon.stub().returns()
})
worker.isMain = false
+ worker.getMainWorker = sinon.stub().returns({
+ id: 1,
+ send: sinon.stub().returns()
+ })
worker.handleKillMessage()
+ expect(worker.getMainWorker().send.calledOnce).toBe(true)
expect(worker.opts.killHandler.calledOnce).toBe(true)
})