PUBLISH rm.users.user1 "Hello, world!"
(integer) 0
RedMessenger is a Redis proxy written for Node.js that ensures that there's always someone listening on your Redis channel - even if no one's immediately there to hear it. It sits in between your Redis instance and your application, exposing a WebSocket on your app's side that delivers a Redis PUBLISH message to a user on your app.
If the user isn't there, that's OK! It'll save that message to that user back on your Redis server. When your user comes back on, it'll handle grabbing all the missed PUBLISHes since last time and send them over the WebSocket.
As part of its queuing mechanism, RedMessenger will take messages with no immediate responder and send them back to Redis.
New message from channel rm.users.user1
Client is not online, queueing message in Redis (rm:users:user1:messages)
New message from channel rm.users.user1
Client is not online, queueing message in Redis (rm:users:user1:messages)
This message will be stored in a message queue on Redis until a user is available to receieve it. This is done by passing a payload on a WebSocket open on RedMessenger containing the user's identifier, along with an optional authentication token.
New connection 127.0.0.1:63769 on *:8080! Waiting for ID...
Assigning id user1 to socket 127.0.0.1:63769.
You're subscribed to rm.users.user1!
rm.users.user1 has 2 messages enqueued, purging!
user1: Purging message 'Hello, world!' from rm.users.user1
user1: Purging message 'My life is a spicy pepper...' from rm.users.user1
Don't worry! RedMessenger will take care of requeueing them for you.
New connection 127.0.0.1:63769 on *:8080! Waiting for ID...
Assigning id user1 to socket 127.0.0.1:63769.
You're subscribed to rm.users.user1!
rm.users.user1 has 2 messages enqueued, purging!
user1: Purging message 'Hello, world!' from rm.users.user1
user1: Client is no longer online, recommitting 'My life is a spicy pepper...' to rm.users.user1 queue.
We gotcha covered!
New message from channel rm.users.user1
Client is not online, queueing message in Redis (rm:users:user1:messages)
New message from channel rm.channels.cats
Client is not online, queueing message in Redis (rm:users:user1:messages)
Client is not online, queueing message in Redis (rm:users:user2:messages)
user5: Sending message 'Meow!' from rm.cats
New connection 127.0.0.1:63769 on *:8080! Waiting for ID...
Assigning id user1 to socket 127.0.0.1:63769.
You're subscribed to rm.users.user1 and rm.cats!
rm.users.user1 has 2 messages enqueued, purging!
user1: Purging message 'Hello, world!' from rm.users.user1
user1: Purging message 'Meow!' from rm.cats
Every message contains some metadata and a message payload.
{
source: 'rm.users.user1',
timestamp: 1438480701712,
bubble: true,
payload: '...'
}What channel the message originated from. For a one-to-one message, this will be rm.users.$uid; for a one-to-many message, this will be rm.groups.$cid.
The time this message was originally PUBLISHed, in Unix time.
Directive that this message should be displayed on the desktop, if the browser supports desktop notifications. Set to true on the first WebSocket established for this user, and false on further concurrent WebSockets opened.
This is to prevent multiple tabs identifying as the same user from spawning one desktop notification each on a single message.
The message payload that was PUBLISHed. This can be whatever you want! (JSON, plaintext, a hash value...)
Write a client to handle server/server.js. An example one is provided for you in client/redmessenger.js!
Here's what you need to do:
- In
server/config.json, configure the configuration options according to your setup:
redis_host: The ip address/hostname of your running Redis instance.
redis_port: The port that your Redis instance is listening on.
ws_port: The port that yourRedMessengerserver should open aWebSocketon.
secure_mode: Iftrue, requires users to authenticate. Connections to a user's message queue must be coupled with a string that matches a user'srm:users:$uid:keystring on Redis, or no messages will be delivered.
rm_route: The route that theWebSocketonRedMessengershould listen on.
queue_expiry: The expiration time for a user's message queue, in seconds. When it expires, clears out a user's entire message queue.
conn_limit: The maximum number of parallel connectionsRedMessengercan accomodate on itsWebSocket. - Open a
socket.iosocket on theWebSocketroute defined on your server'sserver/config.json. - Define an
on('connect')event handler that sends over auid(andkeyifsecure_modeistrue) upon opening a socket to RedMessenger. - Define an
on('message')event handler that does something with a message delivered by RedMessenger. The message will be an object.
function RedMessenger(url, userId, userKey) {
this.url = url;
this.userId = userId;
this.userKey = userKey || '';
var socket; // Our sockets.io socket
if (io) {
socket = io(this.url);
socket.on('connect', function() {
console.log("Connected to RedMessenger!");
var identifier = this.generateIdentifier();
console.log("Authenticating...");
socket.emit('identifier', identifier);
}.bind(this));
socket.on('message', function(message) {
this.onMessage(message);
}.bind(this));
}
this.onMessage = function(message) {
console.log("Message from " + message.source + ": " + message.payload);
}
this.generateIdentifier = function () {
return this.userId + ":" + this.userKey;
}
}Holds user $uid's specific message queue.
Holds user $uid's specific authentication token.
Holds a list of members to deliver a message to rm:channels:$cid to.
PUBLISHing to this channel will deliver a message to $uid directly.
PUBLISHing to this channel will deliver a message to all $uids subscribed to $cid.
- Redis Deliver the message to the
rm.users.user1channel. - RedMessenger If
user1is online, deliver the message touser1over theirWebSocket! - RedMessenger If
user1isn't online, store the message inrm:users:user1:messages. - RedMessenger When
user1is active on ourWebSocket, senduser1all messages fromrm:users:user1:messagesover theirWebSocket.
- Redis Deliver the message to the
rm.channels.catschannel. - RedMessenger For every
$userinrm:channels:cats:subscribers... - RedMessenger If
$useris online, deliver the message to$userover theirWebSocket! - RedMessenger If
$userisn't online, store the message inrm:users:$user:messages. - RedMessenger When
$useris active on ourWebSocket, send$userall messages fromrm:users:$user:messages, including the one delivered torm.channels.catsover theirWebSocket.