You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
2.5 KiB
146 lines
2.5 KiB
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
|
|
var client = require('redis').createClient;
|
|
var parser = require('socket.io-parser');
|
|
var msgpack = require('notepack.io');
|
|
var debug = require('debug')('socket.io-emitter');
|
|
|
|
/**
|
|
* Module exports.
|
|
*/
|
|
|
|
module.exports = init;
|
|
|
|
/**
|
|
* Flags.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
var flags = [
|
|
'json',
|
|
'volatile',
|
|
'broadcast'
|
|
];
|
|
|
|
/**
|
|
* uid for emitter
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
var uid = 'emitter';
|
|
|
|
/**
|
|
* Socket.IO redis based emitter.
|
|
*
|
|
* @param {Object} redis client (optional)
|
|
* @param {Object} options
|
|
* @api public
|
|
*/
|
|
|
|
function init(redis, opts){
|
|
opts = opts || {};
|
|
|
|
if ('string' == typeof redis) {
|
|
redis = client(redis);
|
|
}
|
|
|
|
if (redis && !redis.hset) {
|
|
opts = redis;
|
|
redis = null;
|
|
}
|
|
|
|
if (!redis) {
|
|
if (!opts.socket && !opts.host) throw new Error('Missing redis `host`');
|
|
if (!opts.socket && !opts.port) throw new Error('Missing redis `port`');
|
|
redis = opts.socket
|
|
? client(opts.socket)
|
|
: client(opts.port, opts.host);
|
|
}
|
|
|
|
var prefix = opts.key || 'socket.io';
|
|
|
|
return new Emitter(redis, prefix, '/');
|
|
}
|
|
|
|
function Emitter(redis, prefix, nsp){
|
|
this.redis = redis;
|
|
this.prefix = prefix;
|
|
this.nsp = nsp;
|
|
this.channel = this.prefix + '#' + nsp + '#';
|
|
|
|
this._rooms = [];
|
|
this._flags = {};
|
|
}
|
|
|
|
/**
|
|
* Apply flags from `Socket`.
|
|
*/
|
|
|
|
flags.forEach(function(flag){
|
|
Emitter.prototype.__defineGetter__(flag, function(){
|
|
debug('flag %s on', flag);
|
|
this._flags[flag] = true;
|
|
return this;
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Limit emission to a certain `room`.
|
|
*
|
|
* @param {String} room
|
|
*/
|
|
|
|
Emitter.prototype.in =
|
|
Emitter.prototype.to = function(room){
|
|
if (!~this._rooms.indexOf(room)) {
|
|
debug('room %s', room);
|
|
this._rooms.push(room);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Return a new emitter for the given namespace.
|
|
*
|
|
* @param {String} namespace
|
|
*/
|
|
|
|
Emitter.prototype.of = function(nsp){
|
|
return new Emitter(this.redis, this.prefix, nsp);
|
|
};
|
|
|
|
/**
|
|
* Send the packet.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
Emitter.prototype.emit = function(){
|
|
// packet
|
|
var args = Array.prototype.slice.call(arguments);
|
|
var packet = { type: parser.EVENT, data: args, nsp: this.nsp };
|
|
|
|
var opts = {
|
|
rooms: this._rooms,
|
|
flags: this._flags
|
|
};
|
|
|
|
var msg = msgpack.encode([uid, packet, opts]);
|
|
var channel = this.channel;
|
|
if (opts.rooms && opts.rooms.length === 1) {
|
|
channel += opts.rooms[0] + '#';
|
|
}
|
|
debug('publishing message to channel %s', channel);
|
|
this.redis.publish(channel, msg);
|
|
|
|
// reset state
|
|
this._rooms = [];
|
|
this._flags = {};
|
|
|
|
return this;
|
|
};
|