all files / koa-redis/ index.js

100% Statements 87/87
100% Branches 24/24
100% Functions 12/12
100% Lines 87/87
6 statements, 3 functions Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158                                                      26× 13×   13× 13×   13× 13× 13× 13× 11× 11×           13×       13× 13× 13× 13× 13× 13× 13× 13× 13× 13×   13× 13×   13× 13× 13×       13×       13×       13×       13× 13× 13×       16× 16× 16×                           13× 13×        
/**!
 * koa-redis - index.js
 * Copyright(c) 2015
 * MIT Licensed
 *
 * Authors:
 *   dead_horse <dead_horse@qq.com> (http://deadhorse.me)
 */
 
'use strict';
 
/**
 * Module dependencies.
 */
 
var EventEmitter = require('events').EventEmitter;
var debug = require('debug')('koa-redis');
var redis = require('redis');
var redisWrapper = require('co-redis');
var util = require('util');
var wrap = require('co-wrap-all');
 
/**
 * Initialize redis session middleware with `opts` (see the README for more info):
 *
 * @param {Object} options
 *   - {Object} client       redis client (overides all other options except db and duplicate)
 *   - {String} socket       redis connect socket (DEPRECATED: use 'path' instead)
 *   - {String} db           redis db
 *   - {Boolean} duplicate   if own client object, will use node redis's duplicate function and pass other options
 *   - {String} pass         redis password (DEPRECATED: use 'auth_pass' instead)
 *   - {Any} [any]           all other options inclduing above are passed to node_redis
 */
var RedisStore = module.exports = function (options) {
  if (!(this instanceof RedisStore)) {
    return new RedisStore(options);
  }
  EventEmitter.call(this);
  options = options || {};
 
  var client;
  options.auth_pass = options.auth_pass || options.pass || null;     // For backwards compatibility
  options.path = options.path || options.socket || null;             // For backwards compatibility
  if (!options.client) {
    debug('Init redis new client');
    client = redis.createClient(options);
  } else {
    if (options.duplicate) {                                         // Duplicate client and update with options provided
      debug('Duplicating provided client with new options (if provided)');
      var dupClient = options.client;
      delete options.client;
      delete options.duplicate;
      client = dupClient.duplicate(options);                         // Useful if you want to use the DB option without adjusting the client DB outside koa-redis
    } else {
      debug('Using provided client');
      client = options.client;
    }
  }
 
  if (options.db) {
    debug('selecting db %s', options.db)
    client.select(options.db);
    client.on('connect', function() {
      client.send_anyways = true;
      client.select(options.db);
      client.send_anyways = false;
    });
  }
 
  client.on('error', this.emit.bind(this, 'error'));
  client.on('end', this.emit.bind(this, 'end'));
  client.on('end', this.emit.bind(this, 'disconnect'));              // For backwards compatibility
  client.on('connect', this.emit.bind(this, 'connect'));
  client.on('reconnecting', this.emit.bind(this, 'reconnecting'));
  client.on('ready', this.emit.bind(this, 'ready'));
  client.on('warning', this.emit.bind(this, 'warning'));
  this.on('connect', function() {
    debug('connected to redis');
    this.connected = client.connected;
  });
  this.on('ready', function() {
    debug('redis ready');
  });
  this.on('end', function() {
    debug('redis ended');
    this.connected = client.connected;
  });
  // No good way to test error
  /* istanbul ignore next */
  this.on('error', function() {
    debug('redis error');
    this.connected = client.connected;
  });
  // No good way to test reconnect
  /* istanbul ignore next */
  this.on('reconnecting', function() {
    debug('redis reconnecting');
    this.connected = client.connected;
  });
  // No good way to test warning
  /* istanbul ignore next */
  this.on('warning', function() {
    debug('redis warning');
    this.connected = client.connected;
  });
 
  //wrap redis
  this._redisClient = client;
  this.client = redisWrapper(client);
  this.connected = client.connected;
};
 
util.inherits(RedisStore, EventEmitter);
 
RedisStore.prototype.get = function *(sid) {
  var data = yield this.client.get(sid);
  debug('get session: %s', data || 'none');
  if (!data) {
    return null;
  }
  try {
    return JSON.parse(data.toString());
  } catch (err) {
    // ignore err
    debug('parse session error: %s', err.message);
  }
};
 
RedisStore.prototype.set = function *(sid, sess, ttl) {
  if (typeof ttl === 'number') {
    ttl = Math.ceil(ttl / 1000);
  }
  sess = JSON.stringify(sess);
  if (ttl) {
    debug('SETEX %s %s %s', sid, ttl, sess);
    yield this.client.setex(sid, ttl, sess);
  } else {
    debug('SET %s %s', sid, sess);
    yield this.client.set(sid, sess);
  }
  debug('SET %s complete', sid);
};
 
RedisStore.prototype.destroy = function *(sid) {
  debug('DEL %s', sid);
  yield this.client.del(sid);
  debug('DEL %s complete', sid);
};
 
RedisStore.prototype.quit = function* () {                         // End connection SAFELY
  debug('quitting redis client');
  yield this.client.quit();
};
 
wrap(RedisStore.prototype);
 
RedisStore.prototype.end = RedisStore.prototype.quit;              // End connection SAFELY. The real end() command should never be used, as it cuts off to queue.