示例#1
0
function destroyWorker(worker, exitCode, signal, instructions) {
  exitCode = typeof exitCode === 'number' ? exitCode : signal ? 128: 0;

  var config = this._privateData.config;
  var workerPid = worker.pid;

  // Sound the death knell
  this.emit('end', {
    type: 'end',
    role: 'worker',
    id: workerPid,
    owner: process.pid,
    data: {
      reason: exitCode !== 0 ? 'fired' : 'quit',
      exitCode: exitCode,
      duration: Date.now() - this._privateData.workerStartTimes[workerPid]
    }
  });

  // See if there are other workers remaining
  var hasWorkersLeft = false;
  for (var workerId in this._privateData.workers) {
    if (this._privateData.workers[workerId].pid !== workerPid) {
      hasWorkersLeft = true;
      break;
    }
  }


  // Clear any remaining timeouts
  var workerTimeoutId = this._privateData.workerTimeoutIds[workerPid];
  if (workerTimeoutId) {
    safe.clearTimeout(workerTimeoutId);
    workerTimeoutId = null;
  }

  // Clean up storage
  delete this._privateData.workerStartTimes[workerPid];
  delete this._privateData.workerTimeoutIds[workerPid];
  delete this._privateData.workers[workerPid];

  // Reinforcements!!! Rise from the ashes!
  // Create another Worker process when one Worker exits.
  if (config.continuous === true) {
    var createWorkerFn = createWorker.bind(this, instructions);
    if (config.stagger === true && typeof config.staggeredStart === 'number' && config.staggeredStart >= 0) {
      safe.setTimeout(createWorkerFn, config.staggeredStart);
    }
    else {
      process.nextTick(createWorkerFn);
    }
  }
  // Legion itself should bail out if no workers remain
  else if (!hasWorkersLeft) {
    die.call(this, exitCode);
  }
}
示例#2
0
ReverseProxy.prototype.unregister = function (src, target) {
  if (this.opts.cluster && cluster.isMaster) return this;

  if (!src) {
    return this;
  }

  src = prepareUrl(src);
  var routes = this.routing[src.hostname] || [];
  var pathname = src.pathname || '/';
  var i;

  for (i = 0; i < routes.length; i++) {
    if (routes[i].path === pathname) {
      break;
    }
  }

  if (i < routes.length) {
    var route = routes[i];

    if (target) {
      target = prepareUrl(target);
      _.remove(route.urls, function (url) {
        return url.href === target.href;
      });
    } else {
      route.urls = [];
    }

    if (route.urls.length === 0) {
      routes.splice(i, 1);
      var certs = this.certs;
      if (certs) {
        if (certs[src.hostname] && certs[src.hostname].renewalTimeout) {
          safe.clearTimeout(certs[src.hostname].renewalTimeout);
        }
        delete certs[src.hostname];
      }
    }

    this.log && this.log.info({ from: src, to: target }, 'Unregistered a route');
  }
  return this;
};
示例#3
0
//
// Whether natural or at the hand of our enemy, we all eventually meet our end.
//
function die(exitCode) {
  var theExitCode = this._privateData.theExitCode;
  var wasExitingAlready = typeof theExitCode === 'number';
  var finalExitCode = wasExitingAlready ? theExitCode : typeof exitCode === 'number' ? exitCode : 0;

  // Sound the death knell
  this.emit('end', {
    type: 'end',
    role: 'legion',
    id: process.pid,
    owner: null,
    data: {
      reason: finalExitCode !== 0 ? 'fired' : 'quit',
      exitCode: finalExitCode,
      duration: Date.now() - this._privateData.startTime
    }
  });

  // Clear any timeouts
  var maxTimeoutId = this._privateData.maxTimeoutId;
  if (maxTimeoutId) {
    safe.clearTimeout(maxTimeoutId);
    maxTimeoutId = null;
  }
  delete this._privateData.maxTimeoutId;
  
  // Clean up
  this._privateData.startTime = null;
  this._privateData.theExitCode = null;
  this._privateData.alreadyDead = true;

  // Exit forcibly but only if someone else didn't already invoke the exit
  if (!wasExitingAlready) {
    process.exit(finalExitCode);
  }

  return this;
};
示例#4
0
Legion.prototype.exit = function(exitCode) {
  // Die, workers! Die!
  var worker, workerPid;
  for (var workerId in this._privateData.workers) {
    worker = this._privateData.workers[workerId];
    workerPid = worker.pid;
    worker.kill('SIGINT');

    // The above `kill` calls will NOT react synchronously, so
    // we also need to manually announce the Workers' exit for them
    // before they ACTUALLY exit
    this.emit('end', {
      type: 'end',
      role: 'worker',
      id: workerPid,
      owner: process.pid,
      data: {
        reason: exitCode !== 0 ? 'fired' : 'quit',
        exitCode: exitCode,
        duration: Date.now() - this._privateData.workerStartTimes[workerPid]
      }
    });

    // Clear any remaining timeouts
    var workerTimeoutId = this._privateData.workerTimeoutIds[workerPid];
    if (workerTimeoutId) {
      safe.clearTimeout(workerTimeoutId);
      workerTimeoutId = null;
    }

    // Clean up storage
    delete this._privateData.workerStartTimes[workerPid];
    delete this._privateData.workerTimeoutIds[workerPid];
    delete this._privateData.workers[workerPid];
  }

  return die.call(this, exitCode);
};