socketio / socket.io-redis-adapter Goto Github PK
View Code? Open in Web Editor NEWAdapter to enable broadcasting of events to multiple separate socket.io server nodes.
Home Page: https://socket.io/docs/v4/redis-adapter/
License: MIT License
Adapter to enable broadcasting of events to multiple separate socket.io server nodes.
Home Page: https://socket.io/docs/v4/redis-adapter/
License: MIT License
expose the redis instance so that we can reuse it for custom data storage.
Please revert this commit which removes the Redis UNIX domain socket support:
Background: Redis server can be accessed in two ways.
Multiple clients can use the same UNIX domain socket file at the same time. Comment in the revert indicates that there must be a some sort of misunderstanding about that.
I have a cluster with 10 workers handling socket.io connections at the same time. I'd like to use this library to make them to work together. I prefer to use UNIX domain sockets instead of local TCP connections because UNIX domain socket provide a better performance on Linux as they bypass the TCP/IP stack.
I'm developing a project where we have multiple Node.js instances and we use socket.io-redis to broadcast to all clients of all instances. This works but it seems to consume lot's of CPU.
I've done a couple of tests:
I'm using a "stresstest" where I create 100 namespaces with each 2 clients and where one client broadcasts something to the other client, every second (with {state: 'mystate'} as data).
(I'm using PM2 to start multiple instances and it's monitor functionality to monitor the cpu)
I've used the debug module to see what's going on on the other instances when I use socket.io-redis and I see it's basicly lot's of socket.io-redis ignore different namespace
.
I think socket.io-redis isn't optimized for "lot's" of namespaces?
Hey everyone,
I am sorry but I cannot get my head wrapped around it.
What I want to do is to have one node (or one class of nodes) A that is handling client to server connections. All messages that clients send to node A should be kinda "dumped" in to the redis database where node (class) B is listening on message of type "X" and if it sees any, does stuff.
Does anyone have a basic example on how to achieve this? Especially a way to create a Socket.IO service that is not listening to the outside world but only to redis and gets messages from other nodes is what I cannot achieve to implement.
Thanks in advance
Levin
Following he docs
var redis = require('socket.io-redis');
var adapter = redis('localhost:6379');
adapter.pubClient.on('error', function(){});
adapter.subClient.on('error', function(){});
Error
adapter.pubClient.on('error', function () {});
^
TypeError: Cannot read property 'on' of undefined
Has the api changed ?
Here is my case: nodejs server receives messages from AMQP
, then push those messages to UI through socket.io-redis
.
I try to call emit()
function in the callback of AMQP
, it works well. However, I can NOT find data in redis
server?
Codes
var redisPort = 6379,
redisHost = 'localhost';
var app = require('express')(),
http = require('http').Server(app),
io = require('socket.io')(http),
redisAdapter = require('socket.io-redis'),
redis = require('redis');
var
pub = redis.createClient(redisPort, redisHost),
sub = redis.createClient(redisPort, redisHost, {detect_buffers: true});
//
io.adapter( redisAdapter({pubClient: pub, subClient: sub}) );
app.get('/', function(req, res){
res.sendFile('index.html');
});
io.on('connection', function(socket){
console.log("web socket connection ...");
socket.join('room');
socket.on('disconnect', function(){
console.log("socketio diconnect...");
});
});
callback function in AMQP
function response(msg){
io.to('room').emit('online', msg);
}
...
ch.consume(queue, response, {noAck: true});
Am I right to use this API emit()
? or any other API?
I use socket.io-redis with my node js cluster app. Instead of just exiting on SIGTERM and SIGINT, I gracefully exit and close all connections. However, using the socket.io-redis my child processes never exit, problaby redis connection is persisted, leaving a dead process that has to be forced killed using kill -9
. Here is a quick reproduction script:
cluster = require('cluster');
if (cluster.isMaster) {
cluster.fork();
process.on('SIGTERM', gracefulMasterExit).on('SIGINT', gracefulMasterExit);
process.on('exit', function () {
console.log("Successfully shut down");
});
function gracefulMasterExit() {
console.log("Got SIGINT or SIGTERM, gracefully exiting");
}
} else {
var server = require('http').Server();
var io = require('socket.io')(server);
io.adapter(require('socket.io-redis')('localhost:6379'));
server.listen(3000);
process.on('SIGTERM', gracefulExit).on('SIGINT', gracefulExit);
function gracefulExit() {
console.log("Worker " + cluster.worker.process.pid + " exiting gracefully");
cluster.worker.disconnect();
}
}
After running this you should see Worker <PID> exiting gracefully
, but if you look at your process manager you will still see that worker running with the master process dead. In this particular case sending SIGTERM or SIGINT will trigger a channel closed error but in my actual code the program will just return leaving the worker running in the background. Commenting out the redis adapter line will resolve the problem.
Thanks for taking a look at this!
events.js:72
throw er; // Unhandled 'error' event
^
Error: 58 trailing bytes
at Object.decode (/vagrant/laravel/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:200:47)
at Redis.onmessage (/vagrant/laravel/node/node_modules/socket.io-redis/index.js:95:24)
at RedisClient.emit (events.js:117:20)
at RedisClient.return_reply (/vagrant/laravel/node/node_modules/redis/index.js:696:22)
at HiredisReplyParser.<anonymous> (/vagrant/laravel/node/node_modules/redis/index.js:321:14)
at HiredisReplyParser.emit (events.js:95:17)
at HiredisReplyParser.execute (/vagrant/laravel/node/node_modules/redis/lib/parser/hiredis.js:43:18)
at RedisClient.on_data (/vagrant/laravel/node/node_modules/redis/index.js:547:27)
at Socket.<anonymous> (/vagrant/laravel/node/node_modules/redis/index.js:102:14)
at Socket.emit (events.js:95:17)
Easy to reproduce: start 2 node processes the have socket.io-redis configured, broadcast a message on one of the processes, the other one crashes on decoding of the message.
When I run redis-cli:
127.0.0.1:6379> PSUBSCRIBE socket.io#*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "socket.io#*"
3) (integer) 1
1) "pmessage"
2) "socket.io#*"
3) "socket.io#8CwXOc"
4) "\x92\x83\xa4type\x02\xa4data\x92\xa3new\x81\xa5title\xa8New note\xa3nsp\xa6/notes\x82\xa5rooms\xc4\xa5flags\xc4"
This gets called on a new message:
Redis.prototype.onmessage = function(pattern, channel, msg){
the msg has value:
efbfbdefbfbdefbfbd7479706502efbfbd64617461efbfbdefbfbd6e6577efbfbdefbfbd7469746c65efbfbd4e6577206e6f7465efbfbd6e7370efbfbd2f6e6f746573efbfbdefbfbd726f6f6d73efbfbdefbfbd666c616773efbfbd
Redis version: 2.8.17
Node version: 0.10.32
Socket.io version: 1.1.0
Socket.io-redis version: 0.1.3
Redis package version: 0.12.1
I see that this repository contains bunch of unreleased changes.
When do you plan to release it?
Hey,
io.sockets.adapter.rooms
doesn't seems to have the list of rooms created on other nodes.
am I missing some thing? or this isn't possibile right now with socket.io-redis adapter?
thanks.
Regarding to: socketio/socket.io#1457
In the previous version of socket.io is concept of stores, in version 1.0 there are adapters. Stores in previous version was really susceptible for memory leaks and other errors. How this was fixed in version 1.0?
I couldn't find a good explanation of this concept. Basically there is a poor information stream for version 1.0
What would be the best way to handle syncing namespace creation among clustered node.js instances?
When one instance creates namespaces and a client connects to another instance it won't find these namespaces and can't connect.
Is this something socket.io-redis should do or should I write my own pub/sub system to handle this?
Is there a way to do this across multiple node processes in the recent v1.0 release?
I saw this was a very requested feature. Is there a chance this gets implemented in a the near future? If not, has anyone succeeded in simulating this functionality based on the current 1.0 version?
Thanks!
I use socket.io-redis for a game chat.
and daily active users are more than millions.
but we have recently found some bugs.
firstly we changed join function like the following code..
Socket.prototype.join = function(room, fn){
debug('joining room %s', room);
var self = this;
if (~this.rooms.indexOf(room)){
fn && fn();
return this;
}
this.adapter.add(this.id, room, function(err){
if (err) return fn && fn(err);
debug('joined room %s', room);
if (self.rooms.indexOf(room) == -1) {
self.rooms.push(room);
}
fn && fn(null);
});
return this;
};
the problem of the original join function is that if the user has already joined the same room as the one the user trying to join, callback function (fn) does not trigger.
secondly, if the user join a room several times (In my unittest, a user trying to join the same room thousands times),
the code..
this.adapter.add(this.id, room, function(err) <<--- will be triggered later ...
and the result is that the user has joined the same room multiple times
something like this..
socket.rooms => ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
if you like this code, please change the source code...
From the readme, I can handle Redis connection error as follows:
adapter.pubClient.on('error', function(){});
adapter.subClient.on('error', function(){});
But I couldn't do it at all. Turns out the latest release version (0.1.4) doesn't implement that. Can you release a version that matches the documentation? If not, I think the documentation should be updated or at least made clear to avoid people from pulling their hair. Thanks!
Is there any way to target specific socket connections, from an instance that doesn't have the connection to that socket connection?
I'm afraid this requires similar functionality as rooms, which also isn't implemented yet.
in index.js,
var pieces = channel.split('#'); change this bit of code into this
var pieces = channel.toString().split('#');
and it works.
I'm wondering if there is a common solution to list people in a room when using multi-instance setup?
I have the impression redis only knows how many servers are subscribed to a channel but not how many users?
thank you
hello, I am new to learn socket.io and redis.
I wanna to know what mean of pubClient and subClient, thanks
Hi,
I forked yesterday this repo: https://github.com/liviuignat/chat-example-cluster, where basically I am trying to make the chat sample application with cluster and socket.io-redis so I can post it on Heroku and have a valid, strong sample of socket.io spawned over multiple node processes. The heroku url where it is posted is this: http://chat-example-cluster.herokuapp.com/
There seems to be more questions than solutions, related to this topic, and no concrete example to make it work, this is why I decided to create this example.
Unfortunately I am having problems with the setup and I would appreciate some help, if you could take a look here (https://github.com/liviuignat/chat-example-cluster/blob/master/index.js).
Most of the times I get "Connection closed before receiving a handshake response" on localhost. On Heroku I get "failed: Error during WebSocket handshake: Unexpected response code: 503" and "et::ERR_INCOMPLETE_CHUNKED_ENCODING".
From what I see nothing is being stored on redis also.
Any help would really be appreciated.
Thanks,
The test suite just hangs when called, it doesn't even time out. This is very strange. I narrowed it down to the 'join' event ack not getting emitted, but I can't understand why it doesn't timeout and instead hangs indefinitely. I'm trying to figure it out.
I have crash error when refresh client: node v4.0, [email protected], [email protected].
/Volumes/working/ibooknail/api/node_modules/socket.io-redis/index.js:213
if (!rooms) return process.nextTick(fn.bind(null, null));
^
TypeError: Cannot read property 'bind' of undefined
at Redis.delAll (/Volumes/working/ibooknail/api/node_modules/socket.io-redis/index.js:213:43)
at Socket.leaveAll (/Volumes/working/ibooknail/api/node_modules/socket.io/lib/socket.js:261:16)
at Socket.onclose (/Volumes/working/ibooknail/api/node_modules/socket.io/lib/socket.js:412:8)
at Client.onclose (/Volumes/working/ibooknail/api/node_modules/socket.io/lib/client.js:230:12)
at emitTwo (events.js:92:20)
at Socket.emit (events.js:172:7)
at Socket.onClose (/Volumes/working/ibooknail/api/node_modules/engine.io/lib/socket.js:248:10)
at WebSocket.g (events.js:260:16)
at emitNone (events.js:67:13)
at WebSocket.emit (events.js:166:7)
at WebSocket.Transport.onClose (/Volumes/working/ibooknail/api/node_modules/engine.io/lib/transport.js:113:8)
at WebSocket.g (events.js:260:16)
at emitTwo (events.js:87:13)
at WebSocket.emit (events.js:172:7)
at WebSocket.cleanupWebsocketResources (/Volumes/working/ibooknail/api/node_modules/ws/lib/WebSocket.js:926:10)
at emitNone (events.js:72:20)
Program node app.js exited with code 1
In my application running node cluster i am not able to upgrade to version 1.0.
I think it does not detect the already existing connection and polls all the running instances.
My config:
var io = socketio.listen(server);
var redis = require('socket.io-redis');
io.set('log level',3);
var redisConf = {
host: 'localhost',
port: 6379
};
if(process.env.REDIS_PORT_6379_TCP_PORT && process.env.REDIS_PORT_6379_TCP_ADDR) {
redisConf.host=process.env.REDIS_PORT_6379_TCP_ADDR;
redisConf.port=process.env.REDIS_PORT_6379_TCP_PORT;
}
io.adapter(redis(redisConf));
io.of('/private').use(passportSocketIo.authorize({
key: 'connect.sid', //the cookie where express (or connect) stores its session id.
secret: config.session.secret, //the session secret to parse the cookie
store: app.sessionStore, //the session store that express uses
cookieParser: cookieParser,
fail: function(data, accept) { // *optional* callbacks on success or fail
console.log('socket auth failed');
accept(); // second param takes boolean on whether or not to allow handshake
},
success: function(data, accept) {
accept();
}
})).on('connection', function (socket) {
GET http://localhost:3000/socket.io/?EIO=2&transport=polling&t=1408474615079-1&sid=KtFoj5tlfhjZQe1AAAAA 400 (Bad Request) socket.io.js:2815
WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=2&transport=websocket&sid=KtFoj5tlfhjZQe1AAAAA' failed: Connection closed before receiving a handshake response
I am able to get data via the socket but there are a log of errors in my console. If i set the cluster worker instances to 1 only everything is fine.
When I run 'npm install' I always get the warning below:
npm WARN package.json [email protected] No repository field.
So I'm trying to run a multi-node system where one user can initiate private contact with another user, potentially across nodes, but I'm not sure how to do this with a multi-node system and socket.io-redis.
Originally with a single node, I was simply attaching session objects to each socket. This allowed me to search for socketIds based on session ids and then send a message accordingly, something like: client1 -> socket-server -> client 2.
But now, I can't search the sockets of one node from another.
I'm assuming there must be a way to collect all the sockets connected to the entire network from the redis cache used by socket.io, but I'm not sure and I don't know how to find out. I've been inspecting redis with a desktop client and I can't see anything being cached by socket-io.
Anyways, is it possible to scan the sockets of one node from another node? Or, is what I'm trying to do even possible in this framework?
Currently an exception is thrown if the specified redis server is not available.
Unfortunately the exception is thrown async by some event where no reasonable try-catch can be put in place.
Would be nice if socket.io-redis would provide functionality to check whether a configuration (host:port) is currently available/valid or not.
I am new to 1.0 so i need some help with this. This is more of a structure question...
I have to use redis in my application but i am also using socket.io to have a sort of an api for client app. And on top of that i want to have multiple nodes running so i installed socket.io-redis and added it as adapter.
The thing that is bugging me is that i want to use node_redis for my redis usage. Can i somehow use that package as adapter for socket.io? Only because i don't want to have:
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
and
var redisnode = require("redis"), client = redisnode.createClient();
I would like to pack that to one connection, any ideas?
Hi!
I have the following setup:
#=========================================================================================
# Application setup
#=========================================================================================
config = require('config')
cluster = require('cluster')
_ = require('underscore')
app = require('express')()
http = require('http').Server(app)
socket = require('socket.io')(http, serveClient: false)
env = require('env')
helpers = require('app/javascripts/shared/helpers')
log = helpers.log
passport = require('passport')
session = require('express-session')
mongoose = require('mongoose')
redis = require('socket.io-redis')
MongoStore = require('connect-mongostore')(session)
socket.adapter(redis(host: 'localhost', port: 6379))
#=========================================================================================
# Forking
#=========================================================================================
if cluster.isMaster
for i in [1..config.workers]
log("Starting worker #{i}")
cluster.fork()
cluster.on 'exit', (worker, code, signal)->
log("Worker #{worker.process.pid} died")
if config.debug
process.exit()
else
cluster.fork()
else
#=======================================================================================
# Instantiate server
#=======================================================================================
domain = require('domain').create()
domain.on 'error', (err)->
log(err.stack || err, 'red')
killtimer = setTimeout ->
process.exit(1)
, config.death_timeout
killtimer.unref()
domain.run ->
server = require('./app/javascripts/server')
unless config.debug
assetsHashMap = {}
for key, value of require('./public/assets/hashmap.json')
assetsHashMap[key.replace('.min', '')] = value
mongoose.connect("mongodb://#{config.mongodb.host}/#{config.mongodb.database}", server: socketOptions: keepAlive: 1)
mongoose.connection.on('error', (e)-> log("MongoDB operation failed: #{e}"))
#=====================================================================================
# Template globals
#=====================================================================================
generateTemplateGlobals = ->
app.locals.pretty = config.debug
app.locals.config = _.omit(_.clone(config), 'server_only_keys', config.server_only_keys...)
app.locals._ = _
app.locals.helpers = helpers
#=====================================================================================
# Global middleware
#=====================================================================================
normalizeUrl = (req, res, next)->
try
decodeURIComponent(req.originalUrl)
catch
url = '/'
log("malformed URL, redirecting to #{url}")
return res.redirect(301, url)
[href, qs...] = req.originalUrl.split('?')
if qs.length > 1 # should be 1?2, [2].length = 1
url = href + '?' + qs.join('&')
log("malformed URL, redirecting to #{url}")
return res.redirect(301, url)
next()
getAsset = (name)->
name = assetsHashMap[name] unless config.debug
"/assets/#{name}"
injectGetAsset = (req, res, next)->
req.app.locals.getAsset = getAsset
next()
generateEnv = (req, res, next)->
res.locals.env.rendered = (new Date).toUTCString()
res.locals.env.lang = require('./config/lang_en_us')
next()
updateUserSession = (req, res, next)->
# env.csrf = req.csrfToken()
req.session._updated = (new Date).toUTCString() # forcing cookie to refresh itself
req.session.touch()
next()
preRouteMiddleware = ->
morgan = require('morgan')
if config.debug
app.use(morgan('dev'))
else
app.use(morgan('default'))
app.use(normalizeUrl)
app.use(require('serve-favicon')(__dirname + '/public/favicon.ico'))
app.use(require('serve-static')(__dirname + '/public', redirect: false))
app.use(require('body-parser').json())
app.use(require('cookie-parser')())
app.use session
key: 'sid'
secret: config.session.secret
cookie: maxAge: config.session.lifetime
store: new MongoStore(mongooseConnection: mongoose.connection)
app.use(passport.initialize())
app.use(passport.session())
app.use(injectGetAsset)
app.use(env.create)
app.use(generateEnv)
app.use(updateUserSession)
postRouteMiddleware = ->
if config.debug
app.use(require('errorhandler')(dumpExceptions: true, showStack: true))
else
app.use(require('compression')())
#=====================================================================================
# Start listening
#=====================================================================================
app.enable('trust proxy') # usually sitting behind nginx
app.disable('x-powered-by')
app.set('port', config.port)
app.set('views', "#{__dirname}/app/templates")
app.set('view engine', 'jade')
app.set('json spaces', 2) if config.debug
app.set('socket', socket)
mongoose.connection.once 'open', ->
log('MongoDB connection established', 'cyan')
generateTemplateGlobals()
preRouteMiddleware()
server.use(app) # Fire up the server, all the routes go here
postRouteMiddleware()
app_root = "http://#{config.hostname}:#{config.port}"
if config.ip
http.listen(app.get('port'), config.ip, -> log("Server listening on #{app_root} (bound to ip: #{config.ip})", 'cyan'))
else
http.listen(app.get('port'), -> log("Server listening on #{app_root} (unbound)", 'cyan'))
With only 1 fork running it works perfectly, though socket seems to use polling instead of websocket as a transport.
Connection to redis is successful:
When I start 4 forks, socket can't finish handshakes anymore. What am I doing wrong?
I'm using redis as adapter and sometimes it gives me the error
TypeError: Object #<Object> has no method 'readUInt64BE'
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:131:18)
at Decoder.map (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:34:23)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:68:17)
at Decoder.map (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:34:23)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:68:17)
at Decoder.map (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:34:23)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:68:17)
at Decoder.array (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:51:21)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:74:17)
at Decoder.map (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:34:23)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:68:17)
at Decoder.array (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:51:21)
at Decoder.parse (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:74:17)
at Object.decode (/var/www/00k-admin/node/node_modules/socket.io-redis/node_modules/msgpack-js/msgpack.js:199:23)
at Redis.onmessage (/var/www/00k-admin/node/node_modules/socket.io-redis/index.js:93:24)
at RedisClient.EventEmitter.emit (events.js:106:17)
I read online that the adapter can be used to authenticate rooms. Is that true? And it is possible with socket.io-redis?
it fails on decoding message
var args = msgpack.decode(msg);
events.js:72
throw er; // Unhandled 'error' event
^
SyntaxError: Unexpected token �
at Object.parse (native)
Since 1.0, socket.io starts to support binary data by encoding object like below
[ '52-17{"a":{"_placeholder":true,"num":0},"b":5,"c":{"_placeholder":true,"num":1}}', <Buffer 41 42 43>, <Buffer 44 45 46> ]
The idea is to extract the binary part out and put a placehoder in the JSON as metadata. However, after encoding (in this call: Adapter.prototype.broadcast.call(this, packet, opts);), the original packet is changed as well. The original packet doesn't have any binary part either so only the JSON with placehoder gets published to redis server.
Maybe changing the order of these two lines can work. Publish the packet before its binary part got taken away.
118 Adapter.prototype.broadcast.call(this, packet, opts);
119 if (!remote) pub.publish(key, msgpack.encode([packet, opts]));
Hey,
I implemented a redis adapter in this way
var socketioPub = m_redis.createClient(null, null, { detect_buffers: true });
socketioPub.on('error', function (err) { ... });
var socketioSub = m_redis.createClient(null, null, { detect_buffers: true });
socketioSub.on('error', function (err) { ... });
io.adapter(m_socketio_redis({ pubClient: socketioPub, subClient: socketioSub }));
So if the redis server e.g. is not running I can handle that error, but I get an unhandled error event from https://github.com/Automattic/socket.io-redis/blob/master/index.js#L73
[...]
function Redis(nsp){
Adapter.call(this, nsp);
var self = this;
sub.psubscribe(prefix + '#*', function(err){
if (err) self.emit('error', err); <--------------------------------
});
sub.on('pmessage', this.onmessage.bind(this));
}
[...]
because there is no event listener attached and I see no way to attach one from the outside. Any ideas?
Best regards!
ioredis seem to perform far better then redis
(https://github.com/luin/ioredis)
I have the following package versions:
{
"redis": "2.0.1",
"socket.io": "1.3.7",
"socket.io-emitter": "0.2.0",
"socket.io-redis": "0.1.4",
}
My redis version is 2.8.21.
When I instantiate socket.io-redis
with return_buffers
set to true for the clients, I get the following error:
channel.split("#") <!-- cannot read split of undefined
If I monkey patch the code in index.js
for socket.io-redis
so that the channel is a string, I get a trailing bytes error. Additionally, when I downgrade redis to 1.0.0
, I get a trailing bytes error.
I can deal with downgrading redis to 1.0.0
. However, no permutation of socket.io-redis
, socket.io-emitter
, and redis
seems to ever solve the trailing bytes error. This is a very critical issue for me. Is there an initiative to fix it in the very near future?
I had exception error when using "socket.io": "1.3.7", "socket.io-redis": "0.2.0", nodejsV4
My config:
var pub = redis(socket_redis.port, socket_redis.host);
var sub = redis(socket_redis.port, socket_redis.host, {
return_buffers: true
});
Error: 367 trailing bytes
at Object.decode (/var/www/api/node_modules/msgpack-js/msgpack.js:200:47)
at Redis.onmessage (/var/www/api/node_modules/socket.io-redis/index.js:93:24)
at emitTwo (events.js:87:13)
at RedisClient.emit (events.js:172:7)
at RedisClient.return_reply (/var/www/api/node_modules/redis/index.js:618:22)
at /var/www/ibooknail-api/node_modules/redis/index.js:309:18
at doNTCallback0 (node.js:419:9)
at process._tickDomainCallback (node.js:389:13)
This is obviously a very popular, useful and important part of Socket.IO which has not been maintained for a while. Has Socket.IO considered appointing a new maintainer? It's a big hassle finding a combination of fixes from all the forks right now.
normally within 1 node instance you could:
emit message from sockets[A] --->node instance -->sockets[B]
emit message from sockets[B] --->node instance -->sockets[A]
now, when i have 10 node instances, client A and client B on different instances, how do I send a message from A to B? Redis seem to only do broadcast.
PS: it seems if you do this on RedisStore it works:
socket.broadcast.emit('msg', data);
but how do I do
sockets[B].emit('msg', data);
I have version 0.12.2 of Node, and I'm not able to get socket.io-redis to launch. I just get this error:
Express server listening on port 3000
events.js:85
throw er; // Unhandled 'error' event
^
Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED
at RedisClient.on_error (C:\Users\JWhite\Downloads\socket.io-redis-sample\node_modules\socket.io-redis\node_modules\redis\index.js:185:24)
at Socket. (C:\Users\JWhite\Downloads\socket.io-redis-sample\node_modules\socket.io-redis\node_modules\redis\index.js:95:14)
at Socket.emit (events.js:107:17)
at net.js:459:14
at process._tickCallback (node.js:355:11)
Any suggestions? Is it possible this package needs to be updated to be compatible with Node 0.12? You can replicate my issue by downloading the package socket.io-redis-sample
from Github using version 12.2 of Node and then running npm install
and npm start
in the base directory. Thanks!
I am using socket.io-emitter
to broadcast an event to a set of channels with a for loop:
In the file, I have:
// in the file
var io = require('socket.io-emitter')({
host: 'localhost',
port: 6379
});
module.exports = {
exampleFunction: function(req, res, next) {
var channels = req.param('channels'),
data = req.param('data');
for (var i=0; i<channels.length; i++) {
io.to(channels[i]).emit('example event', data)
}
}
}
In app.js
, I have socket.io-redis
:
io.adapter(socketio_redis({
host: 'localhost',
port: 6379,
pubClient: redis.createClient(6379, '127.0.0.1'),
subClient: redis.createClient(6379, '127.0.0.1')
}))
When I try to run exampleFunction
, I get the following uncaught error in my console:
Error: 348 trailing bytes
at Object.decode (C:\Users\Zachary\Documents\GitHub\thegraduate_backend\node
_modules\socket.io-redis\node_modules\msgpack-js\msgpack.js:200:47)
at Redis.onmessage (C:\Users\Zachary\Documents\GitHub\thegraduate_backend\no
de_modules\socket.io-redis\index.js:93:24)
at RedisClient.EventEmitter.emit (events.js:106:17)
at RedisClient.return_reply (C:\Users\Zachary\Documents\GitHub\thegraduate_b
ackend\node_modules\redis\index.js:672:22)
at ReplyParser.<anonymous> (C:\Users\Zachary\Documents\GitHub\thegraduate_ba
ckend\node_modules\redis\index.js:309:14)
at ReplyParser.EventEmitter.emit (events.js:95:17)
at ReplyParser.send_reply (C:\Users\Zachary\Documents\GitHub\thegraduate_bac
kend\node_modules\redis\lib\parser\javascript.js:300:10)
at ReplyParser.execute (C:\Users\Zachary\Documents\GitHub\thegraduate_backen
d\node_modules\redis\lib\parser\javascript.js:211:22)
at RedisClient.on_data (C:\Users\Zachary\Documents\GitHub\thegraduate_backen
d\node_modules\redis\index.js:534:27)
at Socket.<anonymous> (C:\Users\Zachary\Documents\GitHub\thegraduate_backend
\node_modules\redis\index.js:91:14)
When I change data
to be something smaller, like:
var data = { testing: true }
I get the same error, but to a smaller number of trailing bytes. e.g. 95 trailing bytes
.
How do I get the list of connected clients in a particular room across nodes.
io.sockets.adapter.rooms seems to have the list of clients only in a specific room.
Hey,
https://github.com/Automattic/socket.io-redis/blob/master/index.js#L44 casts the given port to a number, yet that is also the variable used when passing a Unix socket path to Redis.
May be a hook in the broadcast function would be helpful to do some treatment on remote servers. May be something like this:
//Server.js
io.adapter(adapter({key: 'io:', pubClient: pub, subClient: sub}));
io.of('/').adapter.use('newUser', function(event, data){
this.add(data.id, data.room);
});
//Adapter.js
Redis.prototype.broadcast = function(packet, opts, remote){
//Intercept remote events
if(remote){
var event = packet.data[0];
~Object.keys(this.fns).indexOf(event) && this.fns[event].call(this, event, packet.data[1]);
}
Adapter.prototype.broadcast.call(this, packet, opts);
if (!remote) pub.publish(key, msgpack.encode([packet, opts]));
};
Well socket.io-redis
is broken at the moment. Without some workaround you cant even use it: #73 (comment) and there come another issue, which broke compatibility with emits from socket.io-emitter
, because of change psubscribe
for subscribe
: 800ef74 so other socket.io-emitter
libs wont work too. If that two packages are related, why there is no tests with that package ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.