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 PUBLISH
es 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 PUBLISH
ed, 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 PUBLISH
ed. 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 yourRedMessenger
server should open aWebSocket
on.
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:key
string on Redis, or no messages will be delivered.
rm_route
: The route that theWebSocket
onRedMessenger
should 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 connectionsRedMessenger
can accomodate on itsWebSocket
. - Open a
socket.io
socket on theWebSocket
route defined on your server'sserver/config.json
. - Define an
on('connect')
event handler that sends over auid
(andkey
ifsecure_mode
istrue
) 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.
PUBLISH
ing to this channel will deliver a message to $uid
directly.
PUBLISH
ing to this channel will deliver a message to all $uid
s subscribed to $cid
.
- Redis Deliver the message to the
rm.users.user1
channel. - RedMessenger If
user1
is online, deliver the message touser1
over theirWebSocket
! - RedMessenger If
user1
isn't online, store the message inrm:users:user1:messages
. - RedMessenger When
user1
is active on ourWebSocket
, senduser1
all messages fromrm:users:user1:messages
over theirWebSocket
.
- Redis Deliver the message to the
rm.channels.cats
channel. - RedMessenger For every
$user
inrm:channels:cats:subscribers
... - RedMessenger If
$user
is online, deliver the message to$user
over theirWebSocket
! - RedMessenger If
$user
isn't online, store the message inrm:users:$user:messages
. - RedMessenger When
$user
is active on ourWebSocket
, send$user
all messages fromrm:users:$user:messages
, including the one delivered torm.channels.cats
over theirWebSocket
.