Sails: Sockets not stored in redis and onRedisDisconnect does not work

Created on 19 Jun 2019  路  11Comments  路  Source: balderdashy/sails

Node version: 10.15.3
Sails version _(sails)_: 1.2.3
ORM hook version _(sails-hook-orm)_: 2.1.1
Sockets hook version _(sails-hook-sockets)_: 2.0.0
Grunt hook version _(sails-hook-grunt)_: 4.0.0


It seems that socket connecting to sails are not saved in redis, despite having that set up in config/sockets.js

On a fresh Sails.js installation (generated with sails new and option empty, my config/sockets.js looks like this:

module.exports.sockets = {

  adapter: 'socket.io-redis',
  url: 'redis://127.0.0.1:6379',

  onRedisDisconnect: function () {
    console.log("FOO!!!");
 };

If I now add "socket.io-redis": "~5.2.0", to package.json and run npm install I can lift my Sails app without problems. However, Sails doesn't store anything in redis. If I connect a socket and look into redis (via redis-cli) - it is empty. There is not a single database with a single key. Nothing.

Additionally, if I stop redis, I'll get

error: Redis socket "admin sub" server went offline...
error: Redis socket "admin pub" server went offline...
error: Redis socket "sub" server went offline...
error: Redis socket "pub" server went offline...

but onRedisDisconnect is obviously not called, I never get the console.log

My adapter settings are definitely used by Sails: If I change them to something nonsense, I'll get an error ("Failed to lift app: Error: Redis connection to 127.999.0.1:6379 failed - getaddrinfo ENOTFOUND 127.999.0.1 127.999.0.1:6379").
Same goes if redis is not running, when I try to start Sails.

helpful info or workaround sockets

Most helpful comment

@cschwaderer I just did some poking around in the guts of sails-hook-sockets. It looks like you need to put your onRedisDisconnect (and onRedisReconnect) in sails.config.sockets.adapterOptions

module.exports.sockets = {
  adapter: '@sailshq/socket.io-redis', // Realistically should be the same as 'socket.io-redis' but recommended we use this one as thats what the Sails guys test this stuff against
  url: 'redis://127.0.0.1:6379',

  adapterOptions: {
    onRedisDisconnect: function () {
      console.log(`Aye, redis has given up the goat`)
    },

    onRedisReconnect: function () {
      console.log(`Redis reconnected`)
    },
  },
}

Also FWIW it looks like those dis/reconnect methods will get called several times - Sails uses some socket voodoo under the hood to communicate between processes then there's the methods that are made available to us in userland with their own connection.

Aye, redis has given up the goat
error: Redis socket "admin sub" server went offline...
Aye, redis has given up the goat
error: Redis socket "admin pub" server went offline...
Aye, redis has given up the goat
error: Redis socket "sub" server went offline...
Aye, redis has given up the goat
error: Redis socket "pub" server went offline...
~~ Time passes ~~
Redis reconnected
error: Redis socket "pub" server came back online...
Redis reconnected
error: Redis socket "admin pub" server came back online...
Redis reconnected
error: Redis socket "sub" server came back online...
Redis reconnected
error: Redis socket "admin sub" server came back online...

@madisonhicks _If_ I can find the time I'll try and submit a pull request to the docs (after seeing which options actually work at the root sails.config.sockets and which don't. Not quite sure if I should create another little table on that page for it - will see what I can come up with :smile:

All 11 comments

@cschwaderer Thanks for posting! We'll take a look as soon as possible.

In the mean time, there are a few ways you can help speed things along:

  • look for a workaround. _(Even if it's just temporary, sharing your solution can save someone else a lot of time and effort.)_
  • tell us why this issue is important to you and your team. What are you trying to accomplish? _(Submissions with a little bit of human context tend to be easier to understand and faster to resolve.)_
  • make sure you've provided clear instructions on how to reproduce the bug from a clean install.
  • double-check that you've provided all of the requested version and dependency information. _(Some of this info might seem irrelevant at first, like which database adapter you're using, but we ask that you include it anyway. Oftentimes an issue is caused by a confluence of unexpected factors, and it can save everybody a ton of time to know all the details up front.)_
  • read the code of conduct.
  • if appropriate, ask your business to sponsor your issue. _(Open source is our passion, and our core maintainers volunteer many of their nights and weekends working on Sails. But you only get so many nights and weekends in life, and stuff gets done a lot faster when you can work on it during normal daylight hours.)_
  • let us know if you are using a 3rd party plugin; whether that's a database adapter, a non-standard view engine, or any other dependency maintained by someone other than our core team. _(Besides the name of the 3rd party package, it helps to include the exact version you're using. If you're unsure, check out this list of all the core packages we maintain.)_

Please remember: never post in a public forum if you believe you've found a genuine security vulnerability. Instead, disclose it responsibly.

For help with questions about Sails, click here.

Hi, @cschwaderer! Thanks for inquiring. Can you tell me the version of socket.io-redis you're using? Also, would it be possible for you to create a repo of the bit that's giving you problems? Thanks!

Hi, @madisonhicks
Thanks for your reply.
I've put my empty Sails instance with the changed config/sockets.js to Github:
https://github.com/cschwaderer/sailsTest

As mentioned above, my version of "socket.io-redis" is 5.2.0 (the latest, BTW)

Thanks, @cschwaderer! Can't believe I missed the socket.io-redis version in your original write-up—sorry about that 馃槄.

Could you try setting the adapter to '@sailshq/socket.io-redis' (per the config.sockets docs page)? I'll keep digging in the meantime.

Sorry for the delay, I somehow didn't get the notificiation email by Github

Changing the adapter doesn't seem to solve the problem. Behavior is the same for me.

My socket configs looks now like this:

module.exports.sockets = {    
  adapter: '@sailshq/socket.io-redis',
  url: 'redis://127.0.0.1:6379',

  onRedisDisconnect: function () {
    console.log("FOO!!!");
  }
};

And again, what I do for testing:

  • Start Sails via node app.js --port 1399
  • Wait till Sails is up
  • Start a small script which connects as a socket. Script looks like this:
var socketIOClient = require('socket.io-client');
var sailsIOClient = require('sails.io.js');
var io = sailsIOClient(socketIOClient);
io.sails.url = 'http://localhost:1399';
io.socket.on('connect', function() {
    console.log("CONNECTED");
});
  • Wait till the script prints:

    CONNECTED

    |> Now connected to http://localhost:1399.
    ___/ For help, see: http://bit.ly/2q0QDpf
    (using sails.io.js node SDK @v1.2.1)
    Connected at: Thu Jul 04 2019 10:42:59 GMT+0200 (GMT+02:00)

  • Run redis-cli

  • Run command KEYS *
    -> Output is

127.0.0.1:6379> KEYS *
(empty list or set)

  • Stop script -> nothing happens

Hey, @cschwaderer, sorry for the wait!

First, regarding the storage of socket information in Redis: I'm not entirely sure that's expected Redis behavior. I'm given to understand that Redis does store session data, but with sockets it acts instead as a message broker.

The business with onRedisDisconnect is certainly strange. The docs state that onRedisDisconnect is _not_ automatically called if you're providing your own Redis clients, but I don't think I'm seeing you do that in your repo... is that correct?

If Sails doesn't store anything concerning sockets in Redis and that's on purpose, that raises two questions for me:

  1. Why is it possible to set Redis as a socket adapter if it is not used? In my opinion, that causes just confusion.
  2. How can I get a list of all sockets currently connected to all Sails instances of a cluster? That was my original intention/requirement. I had assumed it should be stored in Redis and it might be a bug that it's not the case.

@cschwaderer IIRC Redis is used internally to send messages/socket events between multiple Sails processes (think cluster, PM2 or multiple application servers), but you'll probably never see anything relevant if you look at the data stored in redis as it'll only be there as long as neccessary for all instances of your Sails app to broadcast events to socket clients.

This little snippet should give you a list of IDs of connected sockets across processes:

sails.io.of('/').clients((err, sockets) => {
  console.log('Connected socket IDs:', sockets)
})

Some info about it and other fun stuff is available here: https://github.com/socketio/socket.io-redis#redisadapterclientsroomsarray-fnfunction

@texh Many thanks for those hints! That certainly explains the matter.
Seems like that just the question of onRedisDisconnect remains open.

@cschwaderer I just did some poking around in the guts of sails-hook-sockets. It looks like you need to put your onRedisDisconnect (and onRedisReconnect) in sails.config.sockets.adapterOptions

module.exports.sockets = {
  adapter: '@sailshq/socket.io-redis', // Realistically should be the same as 'socket.io-redis' but recommended we use this one as thats what the Sails guys test this stuff against
  url: 'redis://127.0.0.1:6379',

  adapterOptions: {
    onRedisDisconnect: function () {
      console.log(`Aye, redis has given up the goat`)
    },

    onRedisReconnect: function () {
      console.log(`Redis reconnected`)
    },
  },
}

Also FWIW it looks like those dis/reconnect methods will get called several times - Sails uses some socket voodoo under the hood to communicate between processes then there's the methods that are made available to us in userland with their own connection.

Aye, redis has given up the goat
error: Redis socket "admin sub" server went offline...
Aye, redis has given up the goat
error: Redis socket "admin pub" server went offline...
Aye, redis has given up the goat
error: Redis socket "sub" server went offline...
Aye, redis has given up the goat
error: Redis socket "pub" server went offline...
~~ Time passes ~~
Redis reconnected
error: Redis socket "pub" server came back online...
Redis reconnected
error: Redis socket "admin pub" server came back online...
Redis reconnected
error: Redis socket "sub" server came back online...
Redis reconnected
error: Redis socket "admin sub" server came back online...

@madisonhicks _If_ I can find the time I'll try and submit a pull request to the docs (after seeing which options actually work at the root sails.config.sockets and which don't. Not quite sure if I should create another little table on that page for it - will see what I can come up with :smile:

@nahanil Fantastic! 馃挴Thanks for the extensive help on this, we would be quite grateful for a PR if there is time 馃帀

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Alirezamohammadi picture Alirezamohammadi  路  4Comments

visitsb picture visitsb  路  4Comments

pawankorotane picture pawankorotane  路  3Comments

anissen picture anissen  路  3Comments

Salakar picture Salakar  路  4Comments