node package manager

machinepack-redis

node-machine logo machinepack-redis

Docs   Browse other machines   FAQ   Newsgroup

Structured Node.js bindings for Redis.

This package contains relatively low-level functionality, and it is designed to provide building blocks for higher-level abstractions (e.g. an ORM like Waterline).

Installation   NPM version Build Status

$ npm install machinepack-redis --save

Quick Start

The example below contains a ready-to-use function useful for obtaining one-off access to a Redis connection. Under the covers, in the function's implementation, you can see how to manage the Redis connection lifecycle, as well as how to implement thorough, production-level (anal-retentive) error handling.

 
/**
 * Module dependencies
 */
var Redis = require('machinepack-redis');
 
 
/**
 * doSomeStuffWithRedis()
 *
 * An example of a helper function you might write using mp-redis.
 *
 * @required {String} connectionString 
 *   Connection string to use when connecting to Redis.
 *
 * @optional {Function} during 
 *   Lifecycle callback to run once the connection is active.  Receives connection as first arg, and standard Node cb as second.
 *   Expected to call `during` when finished (at which point the connection is released).
 *
 * @optional {Function} onUnexpectedFailure 
 *   Notifier function to run each time an unexpected failure notice is received one way or the other.
 *   Receives relevant Error as 1st argument.
 */
function doSomeStuffWithRedis(opts, done) {
  if (opts.connectionString === undefined) { return done(new Error('`connectionString` is required.')); }
  if (opts.during !== undefined & typeof opts.during !== 'function') {
    return done(new Error('If provided, `during` must be a function.'));
  }
  if (opts.onUnexpectedFailure !== undefined & typeof opts.onUnexpectedFailure !== 'function') {
    return done(new Error('If provided, `onUnexpectedFailure` must be a function.'));
  }
  
  Redis.createManager({
    connectionString: opts.connectionString,
    onUnexpectedFailure: function (err){
      // Use custom notifier function, if one was provided. 
      if (opts.onUnexpectedFailure) {
        opts.onUnexpectedFailure(err);
        return;
      }
      //--• Otherwise, do the default thing (log a warning) 
      console.warn('WARNING: Redis manager emitted a notice about an unexpected failure.  The redis server may have crashed, or become inaccessible.  Error details from Redis:', err);
    }
  }).exec(function (err, report){
    if (err) {
      return done(new Error('Could not create manager due to unexpected error: '+ err.stack));
    }//--• No reason to proceed any further. 
    
    var mgr = report.manager;
    Redis.getConnection({
      manager: mgr
    }).exec(function (err, report){
      if (err) {
        return done(new Error('Could not get connection from manager, due to unexpected error: '+err.stack));
      }//--• No reason to proceed any further. 
      
      // Local var for convenience. 
      var connection = report.connection;
      
      
      console.log('CONNECTED!');
      
      // Now do stuff w/ the connection 
      (opts.during||function noOp(connection, proceed){
        return proceed();
      })(report.connection, function afterwards (err_doingStuff) {
        if (err_doingStuff) {
          console.log('Unexpected error occurred while doing stuff with this Redis connection.  Details: '+err_doingStuff.stack);
          console.log('Nonetheless, continuing on to release the connection and destroy the manager....');
        }// >- continue on to attempt to release the connection and destroy the manager. 
        
        // Always release the connection when finished: 
        Redis.releaseConnection({
          connection: connection
        }).exec({
          error: function (err_releaseConnection){
            console.warn(new Error('Could not release Redis connection due to unexpected error: '+err_releaseConnection.stack));
            // ^^Note that we might want to also still attempt to destroy the manager here, even 
            // though we couldn't release the connection. (However, we don't mess w/ that in this example code.) 
            
            if (err_doingStuff) { return done(err_doingStuff); }
            else {
              console.warn('Triggering success callback anyway, since everything else seemed to work ok...');
              return done();
            }
          },
          success: function (report){
            console.log('Connection released.');
  
            // But ALWAYS destroy the connection manager when finished 
            Redis.destroyManager({manager: mgr}).exec(function (err_destroyMgr){
              if (err_destroyMgr) {
                console.warn(new Error('Could not destroy Redis connection manager due to unexpected error: '+ err_destroyMgr.stack));
                
                if (err_doingStuff) { return done(err_doingStuff); }
                else {
                  console.warn('Triggering success callback anyway, since everything else seemed to work ok...');
                  return done();
                }
              }//--• 
              
              console.log('Manager destroyed.');
              
              // Now, depending on whether we ran into an error above, finish up accordingly. 
              if (err_doingStuff) {
                // Encountered an error along the way, but at least cleanup worked out ok! 
                return done(err_doingStuff);
              }
              else {
                // Done.  No errors, and we cleaned up everything successfully! 
                return done();
              }
              
            }); //</Redis.destroyManager> 
  
          }//</on success :: Redis.releaseConnection()> 
        });//</Redis.releaseConnection()> 
      });//</during (do stuff while redis connection is active)> 
    }); //</Redis.getConnection> 
  }); //</Redis.createManager> 
}//</declare :: doSomeStuffWithRedis()> 
 
 
// Then e.g. you can do: 
doSomeStuffWithRedis({
  connectionString: 'redis://127.0.0.1:6379',
  onUnexpectedFailure: function (err){ console.warn('uh oh, looks like our redis might have just gone down:',err); },
  during: function (connection, proceed) {
    
    // Storing in key `stuff` value `things` 
    Redis.cacheValue({
      connection: connection,
      key: 'stuff',
      value: 'things'
    }).exec(function (err, report){
      if (err) {
        return proceed(new Error('Could not cache value, due to unexpected error.  Error details: '+err.stack));
      }
 
      console.log('stored `stuff` key with `things`');
 
      // Get the cached value back 
      Redis.getCachedValue({
        connection: connection,
        key: 'stuff'
      }).exec(function (err, report){
        if (err) {
          return proceed(new Error('Could not get cached value, due to unexpected error.  Error details:', err.stack));
        }
 
        console.log('stuff `key` contains `%s`', report.value);
 
        // remove keys. Notice that keys is an array of keys to remove 
        Redis.destroyCachedValues({
          connection: connection,
          keys: ['stuff']
        }).exec(function (err, report){
          if (err) {
            return proceed(new Error('Could not get destroy cached values, due to unexpected error.  Error details:', err.stack));
          }
 
          console.log('key `stuff` removed');
 
          // Get the cached value back 
          Redis.getCachedValue({
            connection: connection,
            key: 'stuff'
          }).exec({
            error: function (err){
              return proceed(new Error('Could not get cached value the 2nd time, due to unexpected error.  Error details:', err.stack));
            },
            notFound: function (){
              console.log('As we expected, the `stuff` key was not found this time.  Good!');
              return proceed();
            },
            success: function (){
              return proceed(new Error('Consistency violation: Should not have been able to find `stuff` key the 2nd time!!!  Must be a bug in our code.'));
            }
          }); //</Redis.getCachedValue> 
 
        }); //</Redis.destroyCachedValues> 
      }); //</Redis.getCachedValue> 
    }); //</Redis.cacheValue> 
  }//</during> 
  
}, function afterwards(err) {
  if (err) {
    console.log('Attempted to do some stuff with redis, but encountered an error along the way:',err.stack);
    return;
  }//--• 
  
  console.log('Successfully did some stuff with Redis!');
});
Setup instructions for the example above

First, if your Redis server is not running yet, open a new terminal window and do:

redis-server

Next, copy the example code below to a new .js file somewhere in your project (e.g. examples/basic-usage.js). Then run:

npm install machinepack-redis --save --save-exact

Finally, run the example:

node examples/basic-usage.js

Usage

For the latest usage documentation, version information, and test status of this module, see http://node-machine.org/machinepack-redis. The generated manpages for each machine contain a complete reference of all expected inputs, possible exit states, and example return values. If you need more help, or find a bug, jump into Gitter or leave a message in the project newsgroup.

About   ![Gitter](https://badges.gitter.im/Join Chat.svg)

This is a machinepack, an NPM module which exposes a set of related Node.js machines according to the machinepack specification. Documentation pages for the machines contained in this module (as well as all other NPM-hosted machines for Node.js) are automatically generated and kept up-to-date on the public registry. Learn more at http://node-machine.org/implementing/FAQ.

License

MIT © 2015 contributors