lib/server.js
function shutdown(opts, cb) {
  if(typeof opts === 'function') {
    cb = opts;
    opts = null;
  }
  opts = opts || {};
  var code = opts.code || 0
    , i = -1
    , snapshots = this.state.conf.get(ConfigKey.SAVE)
    , save = typeof opts.save === 'boolean' ? opts.save : null;

  if(save === null) {
    save = snapshots && snapshots.length > 0;
  }

  /* istanbul ignore next: always in test environment */
  if(process.env.NODE_ENV === Constants.TEST) {
    save = false;
  }

  // cannot save a potentially inconsistent data set
  if(ScriptManager.busy && ScriptManager.written) {
    save = false;
  }

  if(Persistence.loading && save) {
    save = false;
    this.log.warning('save skipped while db load in progress');
  }

  this.state.scheduler.kill();

  function iterate() {
    var conn = this.state.getClient(++i);
    if(!conn) return onClose();
    this.log.verbose('terminating client connection %s', conn.client.id);
    conn.close(function onClose() {
      --i;
      iterate();
    });
  }

  function onShutdownComplete() {
    if(this._daemonized) {
      daemon.pid.remove(this.conf);
    }
    this.log.notice('ready to exit, ciao');
    /* istanbul ignore next: always in test environment */
    if(cb === process.exit
      && process.env.NODE_ENV === Constants.TEST
      && !this._daemonized) {
      return;
    }
    cb(code);
  }

  function onClose() {
    // not saving to disc, explicit nosave
    // or not snapshotting (no save points)
    if(!save) return onShutdownComplete();
    this.log.notice('saving the final rdb snapshot before exiting');
    Persistence.saveSync(this.state.store, this.state.conf);
    onShutdownComplete();
    //Persistence.save(this.state.store, this.state.conf, onShutdownComplete);
  }

  this.log.verbose('not accepting connections')

  // TODO: prevent/handle not running error when not listening!
  // TODO: can possibly test the output of address() to know if we
  // TODO: are listening or not. all logic should be the same just
  // TODO: need to skip the call to close()

  // the close callback can fire before the disconnect listener
  // for the last client connection, so onClose is called when the
  // last connection is actually closed, allows us to assert on
  // client connection length
  if(this._tcp) {
    this._tcp.close();
  }

  if(this._unix) {
    this._unix.close();
  }

  onShutdownComplete = onShutdownComplete.bind(this);
  onClose = onClose.bind(this);
  iterate = iterate.bind(this);
  iterate();
}
function shutdown(opts, cb) {
  if(typeof opts === 'function') {
    cb = opts;
    opts = null;
  }
  opts = opts || {};
  var code = opts.code || 0
    , i = -1
    , snapshots = this.state.conf.get(ConfigKey.SAVE)
    , save = typeof opts.save === 'boolean' ? opts.save : null;

  if(save === null) {
    save = snapshots && snapshots.length > 0;
  }

  /* istanbul ignore next: always in test environment */
  if(process.env.NODE_ENV === Constants.TEST) {
    save = false;
  }

  // cannot save a potentially inconsistent data set
  if(ScriptManager.busy && ScriptManager.written) {
    save = false;
  }

  if(Persistence.loading && save) {
    save = false;
    this.log.warning('save skipped while db load in progress');
  }

  this.state.scheduler.kill();

  function iterate() {
    var conn = this.state.getClient(++i);
    if(!conn) return onClose();
    this.log.verbose('terminating client connection %s', conn.client.id);
    conn.close(function onClose() {
      --i;
      iterate();
    });
  }

  function onShutdownComplete() {
    if(this._daemonized) {
      daemon.pid.remove(this.conf);
    }
    this.log.notice('ready to exit, ciao');
    /* istanbul ignore next: always in test environment */
    if(cb === process.exit
      && process.env.NODE_ENV === Constants.TEST
      && !this._daemonized) {
      return;
    }
    cb(code);
  }

  function onClose() {
    // not saving to disc, explicit nosave
    // or not snapshotting (no save points)
    if(!save) return onShutdownComplete();
    this.log.notice('saving the final rdb snapshot before exiting');
    Persistence.saveSync(this.state.store, this.state.conf);
    onShutdownComplete();
    //Persistence.save(this.state.store, this.state.conf, onShutdownComplete);
  }

  this.log.verbose('not accepting connections')

  // TODO: prevent/handle not running error when not listening!
  // TODO: can possibly test the output of address() to know if we
  // TODO: are listening or not. all logic should be the same just
  // TODO: need to skip the call to close()

  // the close callback can fire before the disconnect listener
  // for the last client connection, so onClose is called when the
  // last connection is actually closed, allows us to assert on
  // client connection length
  if(this._tcp) {
    this._tcp.close();
  }

  if(this._unix) {
    this._unix.close();
  }

  onShutdownComplete = onShutdownComplete.bind(this);
  onClose = onClose.bind(this);
  iterate = iterate.bind(this);
  iterate();
}
function shutdown ( opts , cb ) { if ( typeof opts === 'function' ) { cb = opts ; opts = null ; } opts = opts || { } ; var code = opts . code || 0 , i = - 1 , snapshots = this . state . conf . get ( ConfigKey . SAVE ) , save = typeof opts . save === 'boolean' ? opts . save : null ; if ( save === null ) { save = snapshots && snapshots . length > 0 ; } /* istanbul ignore next: always in test environment */ if ( process . env . NODE_ENV === Constants . TEST ) { save = false ; } // cannot save a potentially inconsistent data set if ( ScriptManager . busy && ScriptManager . written ) { save = false ; } if ( Persistence . loading && save ) { save = false ; this . log . warning ( 'save skipped while db load in progress' ) ; } this . state . scheduler . kill ( ) ; function iterate ( ) { var conn = this . state . getClient ( ++ i ) ; if ( ! conn ) return onClose ( ) ; this . log . verbose ( 'terminating client connection %s' , conn . client . id ) ; conn . close ( function onClose ( ) { -- i ; iterate ( ) ; } ) ; } function onShutdownComplete ( ) { if ( this . _daemonized ) { daemon . pid . remove ( this . conf ) ; } this . log . notice ( 'ready to exit, ciao' ) ; /* istanbul ignore next: always in test environment */ if ( cb === process . exit && process . env . NODE_ENV === Constants . TEST && ! this . _daemonized ) { return ; } cb ( code ) ; } function onClose ( ) { // not saving to disc, explicit nosave // or not snapshotting (no save points) if ( ! save ) return onShutdownComplete ( ) ; this . log . notice ( 'saving the final rdb snapshot before exiting' ) ; Persistence . saveSync ( this . state . store , this . state . conf ) ; onShutdownComplete ( ) ; //Persistence.save(this.state.store, this.state.conf, onShutdownComplete); } this . log . verbose ( 'not accepting connections' ) // TODO: prevent/handle not running error when not listening! // TODO: can possibly test the output of address() to know if we // TODO: are listening or not. all logic should be the same just // TODO: need to skip the call to close() // the close callback can fire before the disconnect listener // for the last client connection, so onClose is called when the // last connection is actually closed, allows us to assert on // client connection length if ( this . _tcp ) { this . _tcp . close ( ) ; } if ( this . _unix ) { this . _unix . close ( ) ; } onShutdownComplete = onShutdownComplete . bind ( this ) ; onClose = onClose . bind ( this ) ; iterate = iterate . bind ( this ) ; iterate ( ) ; }
Graceful shutdown stop accepting new connections.
Graceful shutdown stop accepting new connections .