annotate node_modules/socket.io/lib/stores/redis.js @ 70:753414e075a0

danger stash pop
author tzara <rc-web@kiben.net>
date Sat, 26 Oct 2013 13:43:08 +0000
parents 333afcfd3f3a
children
rev   line source
rc-web@69 1
rc-web@69 2 /*!
rc-web@69 3 * socket.io-node
rc-web@69 4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
rc-web@69 5 * MIT Licensed
rc-web@69 6 */
rc-web@69 7
rc-web@69 8 /**
rc-web@69 9 * Module dependencies.
rc-web@69 10 */
rc-web@69 11
rc-web@69 12 var crypto = require('crypto')
rc-web@69 13 , Store = require('../store')
rc-web@69 14 , assert = require('assert');
rc-web@69 15
rc-web@69 16 /**
rc-web@69 17 * Exports the constructor.
rc-web@69 18 */
rc-web@69 19
rc-web@69 20 exports = module.exports = Redis;
rc-web@69 21 Redis.Client = Client;
rc-web@69 22
rc-web@69 23 /**
rc-web@69 24 * Redis store.
rc-web@69 25 * Options:
rc-web@69 26 * - nodeId (fn) gets an id that uniquely identifies this node
rc-web@69 27 * - redis (fn) redis constructor, defaults to redis
rc-web@69 28 * - redisPub (object) options to pass to the pub redis client
rc-web@69 29 * - redisSub (object) options to pass to the sub redis client
rc-web@69 30 * - redisClient (object) options to pass to the general redis client
rc-web@69 31 * - pack (fn) custom packing, defaults to JSON or msgpack if installed
rc-web@69 32 * - unpack (fn) custom packing, defaults to JSON or msgpack if installed
rc-web@69 33 *
rc-web@69 34 * @api public
rc-web@69 35 */
rc-web@69 36
rc-web@69 37 function Redis (opts) {
rc-web@69 38 opts = opts || {};
rc-web@69 39
rc-web@69 40 // node id to uniquely identify this node
rc-web@69 41 var nodeId = opts.nodeId || function () {
rc-web@69 42 // by default, we generate a random id
rc-web@69 43 return Math.abs(Math.random() * Math.random() * Date.now() | 0);
rc-web@69 44 };
rc-web@69 45
rc-web@69 46 this.nodeId = nodeId();
rc-web@69 47
rc-web@69 48 // packing / unpacking mechanism
rc-web@69 49 if (opts.pack) {
rc-web@69 50 this.pack = opts.pack;
rc-web@69 51 this.unpack = opts.unpack;
rc-web@69 52 } else {
rc-web@69 53 try {
rc-web@69 54 var msgpack = require('msgpack');
rc-web@69 55 this.pack = msgpack.pack;
rc-web@69 56 this.unpack = msgpack.unpack;
rc-web@69 57 } catch (e) {
rc-web@69 58 this.pack = JSON.stringify;
rc-web@69 59 this.unpack = JSON.parse;
rc-web@69 60 }
rc-web@69 61 }
rc-web@69 62
rc-web@69 63 var redis = opts.redis || require('redis')
rc-web@69 64 , RedisClient = redis.RedisClient;
rc-web@69 65
rc-web@69 66 // initialize a pubsub client and a regular client
rc-web@69 67 if (opts.redisPub instanceof RedisClient) {
rc-web@69 68 this.pub = opts.redisPub;
rc-web@69 69 } else {
rc-web@69 70 opts.redisPub || (opts.redisPub = {});
rc-web@69 71 this.pub = redis.createClient(opts.redisPub.port, opts.redisPub.host, opts.redisPub);
rc-web@69 72 }
rc-web@69 73 if (opts.redisSub instanceof RedisClient) {
rc-web@69 74 this.sub = opts.redisSub;
rc-web@69 75 } else {
rc-web@69 76 opts.redisSub || (opts.redisSub = {});
rc-web@69 77 this.sub = redis.createClient(opts.redisSub.port, opts.redisSub.host, opts.redisSub);
rc-web@69 78 }
rc-web@69 79 if (opts.redisClient instanceof RedisClient) {
rc-web@69 80 this.cmd = opts.redisClient;
rc-web@69 81 } else {
rc-web@69 82 opts.redisClient || (opts.redisClient = {});
rc-web@69 83 this.cmd = redis.createClient(opts.redisClient.port, opts.redisClient.host, opts.redisClient);
rc-web@69 84 }
rc-web@69 85
rc-web@69 86 Store.call(this, opts);
rc-web@69 87
rc-web@69 88 this.sub.setMaxListeners(0);
rc-web@69 89 this.setMaxListeners(0);
rc-web@69 90 };
rc-web@69 91
rc-web@69 92 /**
rc-web@69 93 * Inherits from Store.
rc-web@69 94 */
rc-web@69 95
rc-web@69 96 Redis.prototype.__proto__ = Store.prototype;
rc-web@69 97
rc-web@69 98 /**
rc-web@69 99 * Publishes a message.
rc-web@69 100 *
rc-web@69 101 * @api private
rc-web@69 102 */
rc-web@69 103
rc-web@69 104 Redis.prototype.publish = function (name) {
rc-web@69 105 var args = Array.prototype.slice.call(arguments, 1);
rc-web@69 106 this.pub.publish(name, this.pack({ nodeId: this.nodeId, args: args }));
rc-web@69 107 this.emit.apply(this, ['publish', name].concat(args));
rc-web@69 108 };
rc-web@69 109
rc-web@69 110 /**
rc-web@69 111 * Subscribes to a channel
rc-web@69 112 *
rc-web@69 113 * @api private
rc-web@69 114 */
rc-web@69 115
rc-web@69 116 Redis.prototype.subscribe = function (name, consumer, fn) {
rc-web@69 117 this.sub.subscribe(name);
rc-web@69 118
rc-web@69 119 if (consumer || fn) {
rc-web@69 120 var self = this;
rc-web@69 121
rc-web@69 122 self.sub.on('subscribe', function subscribe (ch) {
rc-web@69 123 if (name == ch) {
rc-web@69 124 function message (ch, msg) {
rc-web@69 125 if (name == ch) {
rc-web@69 126 msg = self.unpack(msg);
rc-web@69 127
rc-web@69 128 // we check that the message consumed wasnt emitted by this node
rc-web@69 129 if (self.nodeId != msg.nodeId) {
rc-web@69 130 consumer.apply(null, msg.args);
rc-web@69 131 }
rc-web@69 132 }
rc-web@69 133 };
rc-web@69 134
rc-web@69 135 self.sub.on('message', message);
rc-web@69 136
rc-web@69 137 self.on('unsubscribe', function unsubscribe (ch) {
rc-web@69 138 if (name == ch) {
rc-web@69 139 self.sub.removeListener('message', message);
rc-web@69 140 self.removeListener('unsubscribe', unsubscribe);
rc-web@69 141 }
rc-web@69 142 });
rc-web@69 143
rc-web@69 144 self.sub.removeListener('subscribe', subscribe);
rc-web@69 145
rc-web@69 146 fn && fn();
rc-web@69 147 }
rc-web@69 148 });
rc-web@69 149 }
rc-web@69 150
rc-web@69 151 this.emit('subscribe', name, consumer, fn);
rc-web@69 152 };
rc-web@69 153
rc-web@69 154 /**
rc-web@69 155 * Unsubscribes
rc-web@69 156 *
rc-web@69 157 * @api private
rc-web@69 158 */
rc-web@69 159
rc-web@69 160 Redis.prototype.unsubscribe = function (name, fn) {
rc-web@69 161 this.sub.unsubscribe(name);
rc-web@69 162
rc-web@69 163 if (fn) {
rc-web@69 164 var client = this.sub;
rc-web@69 165
rc-web@69 166 client.on('unsubscribe', function unsubscribe (ch) {
rc-web@69 167 if (name == ch) {
rc-web@69 168 fn();
rc-web@69 169 client.removeListener('unsubscribe', unsubscribe);
rc-web@69 170 }
rc-web@69 171 });
rc-web@69 172 }
rc-web@69 173
rc-web@69 174 this.emit('unsubscribe', name, fn);
rc-web@69 175 };
rc-web@69 176
rc-web@69 177 /**
rc-web@69 178 * Destroys the store
rc-web@69 179 *
rc-web@69 180 * @api public
rc-web@69 181 */
rc-web@69 182
rc-web@69 183 Redis.prototype.destroy = function () {
rc-web@69 184 Store.prototype.destroy.call(this);
rc-web@69 185
rc-web@69 186 this.pub.end();
rc-web@69 187 this.sub.end();
rc-web@69 188 this.cmd.end();
rc-web@69 189 };
rc-web@69 190
rc-web@69 191 /**
rc-web@69 192 * Client constructor
rc-web@69 193 *
rc-web@69 194 * @api private
rc-web@69 195 */
rc-web@69 196
rc-web@69 197 function Client (store, id) {
rc-web@69 198 Store.Client.call(this, store, id);
rc-web@69 199 };
rc-web@69 200
rc-web@69 201 /**
rc-web@69 202 * Inherits from Store.Client
rc-web@69 203 */
rc-web@69 204
rc-web@69 205 Client.prototype.__proto__ = Store.Client;
rc-web@69 206
rc-web@69 207 /**
rc-web@69 208 * Redis hash get
rc-web@69 209 *
rc-web@69 210 * @api private
rc-web@69 211 */
rc-web@69 212
rc-web@69 213 Client.prototype.get = function (key, fn) {
rc-web@69 214 this.store.cmd.hget(this.id, key, fn);
rc-web@69 215 return this;
rc-web@69 216 };
rc-web@69 217
rc-web@69 218 /**
rc-web@69 219 * Redis hash set
rc-web@69 220 *
rc-web@69 221 * @api private
rc-web@69 222 */
rc-web@69 223
rc-web@69 224 Client.prototype.set = function (key, value, fn) {
rc-web@69 225 this.store.cmd.hset(this.id, key, value, fn);
rc-web@69 226 return this;
rc-web@69 227 };
rc-web@69 228
rc-web@69 229 /**
rc-web@69 230 * Redis hash del
rc-web@69 231 *
rc-web@69 232 * @api private
rc-web@69 233 */
rc-web@69 234
rc-web@69 235 Client.prototype.del = function (key, fn) {
rc-web@69 236 this.store.cmd.hdel(this.id, key, fn);
rc-web@69 237 return this;
rc-web@69 238 };
rc-web@69 239
rc-web@69 240 /**
rc-web@69 241 * Redis hash has
rc-web@69 242 *
rc-web@69 243 * @api private
rc-web@69 244 */
rc-web@69 245
rc-web@69 246 Client.prototype.has = function (key, fn) {
rc-web@69 247 this.store.cmd.hexists(this.id, key, function (err, has) {
rc-web@69 248 if (err) return fn(err);
rc-web@69 249 fn(null, !!has);
rc-web@69 250 });
rc-web@69 251 return this;
rc-web@69 252 };
rc-web@69 253
rc-web@69 254 /**
rc-web@69 255 * Destroys client
rc-web@69 256 *
rc-web@69 257 * @param {Number} number of seconds to expire data
rc-web@69 258 * @api private
rc-web@69 259 */
rc-web@69 260
rc-web@69 261 Client.prototype.destroy = function (expiration) {
rc-web@69 262 if ('number' != typeof expiration) {
rc-web@69 263 this.store.cmd.del(this.id);
rc-web@69 264 } else {
rc-web@69 265 this.store.cmd.expire(this.id, expiration);
rc-web@69 266 }
rc-web@69 267
rc-web@69 268 return this;
rc-web@69 269 };