text: 'use strict';
  
  const cluster = require('cluster');
  const EventEmitter = require('events').EventEmitter;
  const defaults = require('lodash.defaults');
  const cpuCount = require('os').cpus().length;
  
  const DEFAULT_OPTIONS = {
    workers: cpuCount,
    lifetime: Infinity,
    grace: 5000
  };
  
  const NOOP = () => {};
  
  module.exports = function throng(options, startFunction) {
    options = options || {};
    let startFn = options.start || startFunction || options;
    let masterFn = options.master || NOOP;
  
    if (typeof startFn !== 'function') {
      throw new Error('Start function required');
    }
    if (cluster.isWorker) {
      return startFn(cluster.worker.id);
    }
  
    let opts = isNaN(options) ?
      defaults(options, DEFAULT_OPTIONS) : defaults({ workers: options }, DEFAULT_OPTIONS);
    let emitter = new EventEmitter();
    let running = true;
    let runUntil = Date.now() + opts.lifetime;
  
    listen();
    masterFn();
    fork();
  
    function listen() {
      cluster.on('exit', revive);
      emitter.once('shutdown', shutdown);
      process
        .on('SIGINT', proxySignal)
        .on('SIGTERM', proxySignal);
    }
  
    function fork() {
      for (var i = 0; i < opts.workers; i++) {
        cluster.fork();
      }
    }
  
    function proxySignal() {
      emitter.emit('shutdown');
    }
  
    function shutdown() {
      running = false;
      for (var id in cluster.workers) {
        cluster.workers[id].process.kill();
      }
      setTimeout(forceKill, opts.grace).unref();
    }
  
    function revive(worker, code, signal) {
      if (running && Date.now() < runUntil) cluster.fork();
    }
  
    function forceKill() {
      for (var id in cluster.workers) {
        cluster.workers[id].kill();
      }
      process.exit();
    }
  };
  