'use strict'; const childProcess = require('child_process'); var _require = require('events'); const EventEmitter = _require.EventEmitter; const errorUtils = require('./errorUtils'); const childModule = parseInt(process.versions.node, 10) < 8 ? require.resolve('../../lib/workerfarm/child') : require.resolve('../../src/workerfarm/child'); let WORKER_ID = 0; class Worker extends EventEmitter { constructor(forkModule, options) { super(); this.options = options; this.id = WORKER_ID++; this.sendQueue = []; this.processQueue = true; this.calls = new Map(); this.exitCode = null; this.callId = 0; this.stopped = false; this.fork(forkModule); } fork(forkModule) { let filteredArgs = process.execArgv.filter(v => !/^--(debug|inspect)/.test(v)); let options = { execArgv: filteredArgs, env: process.env, cwd: process.cwd() }; this.child = childProcess.fork(childModule, process.argv, options); this.send({ type: 'module', module: forkModule, child: this.id }); this.child.on('message', this.receive.bind(this)); this.child.once('exit', code => { this.exitCode = code; this.emit('exit', code); }); this.child.on('error', err => { this.emit('error', err); }); } send(data) { if (!this.processQueue) { return this.sendQueue.push(data); } let result = this.child.send(data, error => { if (error && error instanceof Error) { // Ignore this, the workerfarm handles child errors return; } this.processQueue = true; if (this.sendQueue.length > 0) { let queueCopy = this.sendQueue.slice(0); this.sendQueue = []; queueCopy.forEach(entry => this.send(entry)); } }); if (!result || /^win/.test(process.platform)) { // Queue is handling too much messages throttle it this.processQueue = false; } } call(call) { let idx = this.callId++; this.calls.set(idx, call); this.send({ type: 'request', idx: idx, child: this.id, method: call.method, args: call.args }); } receive(data) { if (this.stopped) { return; } let idx = data.idx; let type = data.type; let content = data.content; let contentType = data.contentType; if (type === 'request') { this.emit('request', data); } else if (type === 'response') { let call = this.calls.get(idx); if (!call) { // Return for unknown calls, these might accur if a third party process uses workers return; } if (contentType === 'error') { call.reject(errorUtils.jsonToError(content)); } else { call.resolve(content); } this.calls.delete(idx); this.emit('response', data); } } stop() { this.stopped = true; this.send('die'); setTimeout(() => { if (this.exitCode === null) { this.child.kill('SIGKILL'); } }, this.options.forcedKillTime); } } module.exports = Worker;