Skip to content

Instantly share code, notes, and snippets.

@huttj
Created October 10, 2015 00:48
Show Gist options
  • Save huttj/53107e7f7fdd5a0258be to your computer and use it in GitHub Desktop.
Save huttj/53107e7f7fdd5a0258be to your computer and use it in GitHub Desktop.
Redis pubsub
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Redis pubsub</title>
</head>
<body>
<button id="add">Add 1</button>
<p><span id="count">?</span> click(s)</p>
<script src="/socket.io/socket.io.js"></script>
<script>
var CLIENT_INCREMENT = 'add';
var CLIENT_COUNT = 'count';
var socket = io('http://localhost:{port}');
var add = document.getElementById('add');
var count = document.getElementById('count');
add.addEventListener('click', function () {
socket.emit(CLIENT_INCREMENT);
});
socket.on(CLIENT_COUNT, function (n) {
count.textContent = n;
});
</script>
</body>
</html>
// Make it easy to spin up the server on different ports
var PORT = process.argv[2] || 3000;
// Just some constants to make it easier to modify. Of note is
// that the redis and socket.io event/message names are independent
var CLIENT_INCREMENT = 'add';
var REDIS_INCREMENT = 'increment';
var CLIENT_COUNT = 'count';
var REDIS_COUNT = 'count';
// You need two redis connections, because using `subscribe`
// makes the connection unable to publish messages
var redis = require('redis').createClient();
var sub = require('redis').createClient();
// Standard socket.io fare
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
var fs = require('fs');
var count = 0; // Keep track of the current count, for new connections
var indexHtml; // Cache to avoid reading from disk each time
// Get current count after connecting
redis.get(REDIS_COUNT, function(err, reply) {
log('redis got count', reply);
// If we're the first one, set the count to 0
if (reply == null) {
count = 0;
redis.set(REDIS_COUNT, 0);
} else {
count = Number(reply);
}
});
// Subscribe to messages on the 'incremented' channel
sub.subscribe(REDIS_INCREMENT, noop);
// Get notified when a message is published
sub.on('message', function(channel, message) {
// Ignore messages not on 'incremented' channel
if (channel !== REDIS_INCREMENT) return;
// Update local cache
count++;
// Send count to all connected clients
io.emit(CLIENT_COUNT, count);
});
// Start the server
app.listen(PORT, function(){
log('Running on port:', PORT);
});
io.on('connection', function (socket) {
log('connection', socket.handshake.address);
// Send the current count to the client
socket.emit(CLIENT_COUNT, count);
// When the client generates an 'increment' event,
// increment the global count and notify everyone
socket.on(CLIENT_INCREMENT, function() {
redis.incr(REDIS_COUNT);
redis.publish(REDIS_INCREMENT, count);
});
});
// console.log shorthand
function log() {
console.log.apply(console, arguments);
}
// Serve the index.html to new clients
function handler (req, res) {
if (indexHtml) {
res.writeHead(200);
return res.end(indexHtml);
}
fs.readFile(__dirname + '/index.html', function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
indexHtml = data.toString().replace(/\{port\}/, PORT);
res.writeHead(200);
res.end(indexHtml);
});
}
function noop(){}
{
"name": "Redis pubsub",
"version": "0.0.1",
"description": "Just a short demo of how to use redis to sync across servers.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Joshua Hutt <joshua@huttj.com>",
"license": "MIT",
"dependencies": {
"redis": "^2.1.0",
"socket.io": "^1.3.7"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment