PubSub is a little extension to Sinatra that adds basic publish/subscribe streaming using HTML5 Server Sent Events.
For example, clients can subscribe to events like this:
var es = new EventSource('/subscribe');
es.onmessage = function(e) {
console.log(JSON.parse(e.data));
};
And then you can broadcast events to them like this:
Sinatra::PubSub.publish_all(type: 'tick')
You can subscribe to specific channels:
var es = new EventSource('/subscribe/sites/123');
And publish to them:
Sinatra::PubSub.publish('sites/123', data: 'hi')
You can find a simple demo on Heroku, which streams a 'tick' every second to your browser.
http://sinatra-pubsub-tick.herokuapp.com
- Thin
- Redis
- Sinatra
Add this line to your application's Gemfile:
gem 'sinatra-pubsub'
And then execute:
$ bundle
Or install it yourself as:
$ gem install sinatra-pubsub
Include it in your Sinatra application like so:
require 'sinatra/pubsub'
register Sinatra::PubSub
This creates a /subscribe/*
endpoint, which clients can use with EventSource
.
You can publish to channels using the Sinatra::PubSub.publish_all(msg)
or
Sinatra::publish(channel, msg)
methods.
Messages will be automatically serialized to JSON - you'll need to parse them on the client.
See the ./examples
dir for more use-cases.
It's often a good idea to create a separate streaming server on a subdomain, rather than using your main application server for streaming. This gives you a bit more flexibility, like letting you use a Unicorn for your application server, and Thin for your streaming server. This is a quick guide to creating exactly that on Heroku.
First create your streaming server from the 'basic' example.
git clone https://github.com/maccman/sinatra-pubsub.git
cp -r sinatra-pubsub/examples/basic myapp-stream
cd myapp-stream
bundle install
git init
git add .
git commit -m 'first commit'
heroku create myapp-stream
git push heroku master
Now the server is deployed, you need to setup Redis. If you already have Redis running on your main application server, just run:
heroku config -a myapp-stream | grep REDIS
heroku config:set REDIS_URL=YOUR_REDIS_URL -a myapp-stream
Otherwise install the RedisCloud addon:
heroku addons:add rediscloud -a myapp-stream
heroku config -a myapp-stream | grep REDIS
heroku config:set REDIS_URL=YOUR_REDIS_URL -a myapp-stream
And you're finished! You can subscribe to a channel from any browser like this:
var es = new EventSource('http://myapp-stream.herokuapp.com/subscribe');
es.onmessage = function(e) {
console.log(JSON.parse(e.data));
};
And publish to the stream from any Ruby client connected to the same Redis server:
Sinatra::PubSub.publish_all('Hello World')