Deolu A
Deolu A

Reputation: 798

Websocket + Redis: multiple channels, specific subscriptions/publishing

I'm new to websockets, and am wondering how best to go about this.

My scenario: I have a server that handles different classes of users. For this example, let's say the classes are "mice", "cats", and "dogs"

Each of those classes should have their own channels to listen to for changes e.g. "mice-feed", "cat-feed", and "dog-feed"

My question is: after the server authenticates and determines the class of the current user, what's the best way to have them subscribed to a specific channel, or channel(s), so that when I broadcast messages to said channel(s), I can make sure that only members of particular classes get them (as against everyone currently connected to that server)?

My current code setup looks like this:

    var ws                  =       require('ws');
    var redis               =       require('redis');

/* LOCATION 1 */
// prep redis, for websocket channels
    var pub = redis.createClient();
    var sub = redis.createClient();

    // subscribe to our channels
    sub.subscribe('mice-feed');
    sub.subscribe('cat-feed');
    sub.subscribe('dog-feed');

// declare the server
    const wsServer = new ws.Server({
        noServer: true,
        path: "/",
    });

/* ... removing some code for brevity... */

    wsServer.on("connection", function connection(websocketConnection, connectionRequest) {
        /* LOCATION 2 */
    });

Do I put the redis declarations in LOCATION 1 (where it currently is), or in LOCATION 2 (when a successful connection is established)? Or neither of the above?

(also: I know it's possible to do this on the websocket end directly i.e. iterate through every client and ws.send if some criterion is matched, but iteration can become costly, and I'm wondering if I can do it on a redis-channel wide operation instead)

Upvotes: 0

Views: 1462

Answers (1)

Guy Royse
Guy Royse

Reputation: 4312

If I were building this, my first approach would be this:

// connect to Redis
const client = createClient();
client.on('error', (err) => console.log('Redis Client Error', err));
await client.connect();

// declare the server
const wsServer = new ws.Server(...elided...);

// handle connection
wsServer.on('connection', async (websocketConnection, connectionRequest) => {

  const sub = client.duplicate()

  // figure out the feed
  const feed = 'animal-feed';

  await sub.subscribe(feed, message => {
    ...do stuff...
  });
});

It's pretty straightforward but would result in ever user having a dedicated connect to Redis. That may or may not matter depending on how many users you anticipate having.

Upvotes: 1

Related Questions