it("should fork another worker when exit was unexpected", function () { sinon.stub(this.instance, "warn"); this.worker.suicide = false; cluster.emit("exit", this.worker); cluster.fork.should.be.calledOnce; this.instance.warn.should.be.calledOnce; });
cluster.on('exit', function (worker, code, signal) { var log = console[worker.disableRefork ? 'info' : 'error']; var isExpected = !!disconnects[worker.process.pid]; var isDead = worker.isDead && worker.isDead(); var propertyName = worker.hasOwnProperty('exitedAfterDisconnect') ? 'exitedAfterDisconnect' : 'suicide'; log('[%s] [cfork:master:%s] worker:%s exit (code: %s, %s: %s, state: %s, isDead: %s, isExpected: %s, worker.disableRefork: %s)', utility.logDate(), process.pid, worker.process.pid, code, propertyName, worker[propertyName], worker.state, isDead, isExpected, worker.disableRefork); if (isExpected) { delete disconnects[worker.process.pid]; // worker disconnect first, exit expected return; } if (worker.disableRefork) { // worker is killed by master return; } unexpectedCount++; if (allow()) { newWorker = forkWorker(worker._clusterSettings); newWorker._clusterSettings = worker._clusterSettings; log('[%s] [cfork:master:%s] new worker:%s fork (state: %s)', utility.logDate(), process.pid, newWorker.process.pid, newWorker.state); } else { log('[%s] [cfork:master:%s] don\'t fork new work (refork: %s)', utility.logDate(), process.pid, refork); } cluster.emit('unexpectedExit', worker, code, signal); });
cluster.on('exit', function (worker, code, signal) { if (disconnects[worker.process.pid]) { delete disconnects[worker.process.pid]; // worker disconnect first, exit expected return; } unexpectedCount++; if (allow()) { cluster.fork(); } cluster.emit('unexpectedExit', worker, code, signal); });
cluster.on('exit', function (worker, code, signal) { if (disconnects[worker.process.pid]) { delete disconnects[worker.process.pid]; // worker disconnect first, exit expected return; } unexpectedCount++; if (allow()) { newWorker = forkWorker(worker._clusterSettings); newWorker._clusterSettings = worker._clusterSettings; } cluster.emit('unexpectedExit', worker, code, signal); });
/** * allow refork */ function allow() { if (!refork) { return false; } var times = reforks.push(Date.now()); if (times > limit) { reforks.shift(); } var span = reforks[reforks.length - 1] - reforks[0]; var canFork = reforks.length < limit || span > duration; if (!canFork) { cluster.emit('reachReforkLimit'); } return canFork; }
cluster.on('exit', function (worker, code, signal) { var isExpected = !!disconnects[worker.process.pid]; var isDead = worker.isDead && worker.isDead(); console.error('[%s] [cfork:master:%s] worker:%s exit (code: %s, suicide: %s, state: %s, isDead: %s, isExpected: %s)', Date(), process.pid, worker.process.pid, code, worker.suicide, worker.state, isDead, isExpected); if (isExpected) { delete disconnects[worker.process.pid]; // worker disconnect first, exit expected return; } unexpectedCount++; if (allow(worker)) { newWorker = forkWorker(worker._clusterSettings); newWorker._clusterSettings = worker._clusterSettings; console.error('[%s] [cfork:master:%s] new worker:%s fork (state: %s)', Date(), process.pid, newWorker.process.pid, newWorker.state); } else { console.error('[%s] [cfork:master:%s] don\'t fork new work (refork: %s)', Date(), process.pid, refork); } cluster.emit('unexpectedExit', worker, code, signal); });
}).on('message', function(mesg) { cluster.emit('worker_message', worker, mesg); });
it("should not fork another worker when exit was a suicide", function () { this.worker.suicide = true; cluster.emit("exit", this.worker); cluster.fork.should.not.be.called; });
it("should log activity", function () { this.worker.suicide = true; cluster.emit("exit", this.worker); this.instance.debug.should.be.calledWith("worker[1] exited."); });
it("should log activity", function () { cluster.emit("disconnect", this.worker); this.instance.debug.should.be.calledWith("worker[1] disconnected."); });
it("should bind worker 'message' event", function () { cluster.emit("online", this.worker); this.worker.on.should.be.calledWith("message", sinon.match.func); });
it("should log activity", function () { cluster.emit("online", this.worker); this.instance.debug.should.be.calledWith("worker[1] online."); });