diff --git a/doc/api/cluster.md b/doc/api/cluster.md index d3fb499b89f45b..5b474521698457 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -292,6 +292,29 @@ if (cluster.isMaster) { } ``` +### worker.exitedAfterDisconnect + +* {Boolean} + +Alias to [`worker.suicide`][]. + +Set by calling `.kill()` or `.disconnect()`, until then it is `undefined`. + +The boolean `worker.exitedAfterDisconnect` lets you distinguish between +voluntary and accidental exit, the master may choose not to respawn a worker +based on this value. + +```js +cluster.on('exit', (worker, code, signal) => { + if (worker.exitedAfterDisconnect === true) { + console.log('The worker exited after disconnect.'). + } +}); + +// kill worker +worker.kill(); +``` + ### worker.id * {Number} @@ -690,3 +713,4 @@ socket.on('data', (id) => { [child_process event: 'exit']: child_process.html#child_process_event_exit [child_process event: 'message']: child_process.html#child_process_event_message [`process` event: `'message'`]: process.html#process_event_message +[`worker.suicide`]: #cluster_worker_suicide diff --git a/lib/cluster.js b/lib/cluster.js index 8e8bdefadf03c7..02f78a894a7585 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -31,6 +31,16 @@ function Worker(options) { this.state = options.state || 'none'; this.id = options.id | 0; + Object.defineProperty(this, 'exitedAfterDisconnect', { + get: function() { + return this.suicide; + }, + set: function(val) { + this.suicide = val; + }, + enumerable: true + }); + if (options.process) { this.process = options.process; this.process.on('error', (code, signal) => diff --git a/test/parallel/test-cluster-worker-constructor.js b/test/parallel/test-cluster-worker-constructor.js index 2a96d24a8a3459..bf1d594822edd7 100644 --- a/test/parallel/test-cluster-worker-constructor.js +++ b/test/parallel/test-cluster-worker-constructor.js @@ -9,6 +9,7 @@ var worker; worker = new cluster.Worker(); assert.equal(worker.suicide, undefined); +assert.equal(worker.exitedAfterDisconnect, undefined); assert.equal(worker.state, 'none'); assert.equal(worker.id, 0); assert.equal(worker.process, undefined); @@ -19,6 +20,7 @@ worker = new cluster.Worker({ process: process }); assert.equal(worker.suicide, undefined); +assert.equal(worker.exitedAfterDisconnect, undefined); assert.equal(worker.state, 'online'); assert.equal(worker.id, 3); assert.equal(worker.process, process); diff --git a/test/parallel/test-cluster-worker-exit.js b/test/parallel/test-cluster-worker-exit.js index 60c80ec938555d..3d7dd62bac0563 100644 --- a/test/parallel/test-cluster-worker-exit.js +++ b/test/parallel/test-cluster-worker-exit.js @@ -32,6 +32,8 @@ if (cluster.isWorker) { worker_emitExit: [1, "the worker did not emit 'exit'"], worker_state: ['disconnected', 'the worker state is incorrect'], worker_suicideMode: [false, 'the worker.suicide flag is incorrect'], + worker_exitedAfterDisconnect: [false, + 'the .exitedAfterDisconnect flag is incorrect'], worker_died: [true, 'the worker is still running'], worker_exitCode: [EXIT_CODE, 'the worker exited w/ incorrect exitCode'], worker_signalCode: [null, 'the worker exited w/ incorrect signalCode'] @@ -66,6 +68,8 @@ if (cluster.isWorker) { worker.on('disconnect', function() { results.worker_emitDisconnect += 1; results.worker_suicideMode = worker.suicide; + results.worker_exitedAfterDisconnect = worker.exitedAfterDisconnect; + assert.strictEqual(worker.suicide, worker.exitedAfterDisconnect); results.worker_state = worker.state; if (results.worker_emitExit > 0) { process.nextTick(function() { finish_test(); });