server/lib/sync-lock.js
function request(client, path, callback) {
  var key = SyncLock.generateKey(client.username);
  var id = client.id;

  // Try to set this key/value pair, but fail if the path for the key already exists.
  redis.hsetnx(key, path, id, function(err, reply) {
    if(err) {
      log.error({err: err, client: client}, 'Error trying to set redis key with hsetnx');
      return callback(err);
    }

    if(reply === 1) {
      // Success, we have the lock (path for the key was set). Return a new SyncLock instance
      var lock = new SyncLock(key, id, path);
      log.debug({client: client, syncLock: lock}, 'Lock acquired.');
      return callback(null, lock);
    }

    // Path for key was not set (held by another client). See if the lock owner would be
    // willing to let us take it. We'll wait a bit for a reply, and if
    // we don't get one, assume the client holding the lock, or its server,
    // has crashed, and the lock is OK to take.

    // Act if we don't hear back from the lock owner in a reasonable
    // amount of time, and set the lock ourselves.
    var waitTimer = setTimeout(function() {
      redis.removeListener('lock-response', client._handleLockResponseFn);
      client._handleLockResponseFn = null;

      redis.hset(key, path, id, function(err) {
        if(err) {
          log.error({err: err, client: client}, 'Error setting redis lock key.');
          return callback(err);
        }

        var lock = new SyncLock(key, id, path);
        log.debug({client: client, syncLock: lock}, 'Lock request timeout, setting lock manually.');
        callback(null, lock);
      });
    }, CLIENT_TIMEOUT_MS);
    waitTimer.unref();

    // Listen for a response from the client holding the lock
    client._handleLockResponseFn = function(message) {
      handleLockResponse(message, key, path, client, waitTimer, callback);
    };
    redis.on('lock-response', client._handleLockResponseFn);

    // Ask the client holding the lock to give it to us
    log.debug({client: client}, 'Requesting lock override for ' + path);
    redis.publish(Constants.server.lockRequestChannel, JSON.stringify({key: key, id: id, path: path}));
  });
}
function request(client, path, callback) {
  var key = SyncLock.generateKey(client.username);
  var id = client.id;

  // Try to set this key/value pair, but fail if the path for the key already exists.
  redis.hsetnx(key, path, id, function(err, reply) {
    if(err) {
      log.error({err: err, client: client}, 'Error trying to set redis key with hsetnx');
      return callback(err);
    }

    if(reply === 1) {
      // Success, we have the lock (path for the key was set). Return a new SyncLock instance
      var lock = new SyncLock(key, id, path);
      log.debug({client: client, syncLock: lock}, 'Lock acquired.');
      return callback(null, lock);
    }

    // Path for key was not set (held by another client). See if the lock owner would be
    // willing to let us take it. We'll wait a bit for a reply, and if
    // we don't get one, assume the client holding the lock, or its server,
    // has crashed, and the lock is OK to take.

    // Act if we don't hear back from the lock owner in a reasonable
    // amount of time, and set the lock ourselves.
    var waitTimer = setTimeout(function() {
      redis.removeListener('lock-response', client._handleLockResponseFn);
      client._handleLockResponseFn = null;

      redis.hset(key, path, id, function(err) {
        if(err) {
          log.error({err: err, client: client}, 'Error setting redis lock key.');
          return callback(err);
        }

        var lock = new SyncLock(key, id, path);
        log.debug({client: client, syncLock: lock}, 'Lock request timeout, setting lock manually.');
        callback(null, lock);
      });
    }, CLIENT_TIMEOUT_MS);
    waitTimer.unref();

    // Listen for a response from the client holding the lock
    client._handleLockResponseFn = function(message) {
      handleLockResponse(message, key, path, client, waitTimer, callback);
    };
    redis.on('lock-response', client._handleLockResponseFn);

    // Ask the client holding the lock to give it to us
    log.debug({client: client}, 'Requesting lock override for ' + path);
    redis.publish(Constants.server.lockRequestChannel, JSON.stringify({key: key, id: id, path: path}));
  });
}
function request ( client , path , callback ) { var key = SyncLock . generateKey ( client . username ) ; var id = client . id ; // Try to set this key/value pair, but fail if the path for the key already exists. redis . hsetnx ( key , path , id , function ( err , reply ) { if ( err ) { log . error ( { err : err , client : client } , 'Error trying to set redis key with hsetnx' ) ; return callback ( err ) ; } if ( reply === 1 ) { // Success, we have the lock (path for the key was set). Return a new SyncLock instance var lock = new SyncLock ( key , id , path ) ; log . debug ( { client : client , syncLock : lock } , 'Lock acquired.' ) ; return callback ( null , lock ) ; } // Path for key was not set (held by another client). See if the lock owner would be // willing to let us take it. We'll wait a bit for a reply, and if // we don't get one, assume the client holding the lock, or its server, // has crashed, and the lock is OK to take. // Act if we don't hear back from the lock owner in a reasonable // amount of time, and set the lock ourselves. var waitTimer = setTimeout ( function ( ) { redis . removeListener ( 'lock-response' , client . _handleLockResponseFn ) ; client . _handleLockResponseFn = null ; redis . hset ( key , path , id , function ( err ) { if ( err ) { log . error ( { err : err , client : client } , 'Error setting redis lock key.' ) ; return callback ( err ) ; } var lock = new SyncLock ( key , id , path ) ; log . debug ( { client : client , syncLock : lock } , 'Lock request timeout, setting lock manually.' ) ; callback ( null , lock ) ; } ) ; } , CLIENT_TIMEOUT_MS ) ; waitTimer . unref ( ) ; // Listen for a response from the client holding the lock client . _handleLockResponseFn = function ( message ) { handleLockResponse ( message , key , path , client , waitTimer , callback ) ; } ; redis . on ( 'lock-response' , client . _handleLockResponseFn ) ; // Ask the client holding the lock to give it to us log . debug ( { client : client } , 'Requesting lock override for ' + path ) ; redis . publish ( Constants . server . lockRequestChannel , JSON . stringify ( { key : key , id : id , path : path } ) ) ; } ) ; }
Request a lock for the current client.
Request a lock for the current client .