Skip to content

Instantly share code, notes, and snippets.

@arashm
Last active March 7, 2024 15:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arashm/9840345 to your computer and use it in GitHub Desktop.
Save arashm/9840345 to your computer and use it in GitHub Desktop.
A simple chat app to demonstrate a pub/sub system using Redis and Server-Sent Event(SSE). You can see if you open two browsers, both browsers will get updates when user submits a message.
#!/usr/bin/env ruby
# A simple chat app to demonstrate a pub/sub system using
# Redis and Server-Sent Event(SSE)
require 'sinatra'
require 'sinatra/streaming'
require 'redis'
require 'json'
set :port, 3000
html = <<-EOT
<html><head>
<style>
body { font-size: 16px; }
input#message { width: 300px; }
input#username { width: 100px; }
input { padding: 10px }
</style>
</head><body>
<form>
<!--- there should be a 'name' or serializeArray in JQ wont work --->
<input name='username' id='username' placeholder='Username' value='Guest' />
<input name='message' id='message' placeholder='Send your message' />
<input type='submit' value='send' >
</form>
<div id="messages">
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
function show_message(name, value) {
$('#messages').append("<p><b>" + name + ": </b>" + value + "</p>" )
$('#message').val('')
}
// Connect to SSE
var source = new EventSource('/subscribe');
// When a message received
source.onmessage = function(event) {
var data = JSON.parse(event.data);
show_message(data['username'], data['message']);
}
source.onerror = function(event) {
console.log('got error :(');
}
// Post the message when form submitted
$('form').submit( function(event) {
var form = $(this);
$.post('/send',
form.serializeArray()
);
event.preventDefault();
});
</script>
</body></html>
EOT
get('/') { html }
post '/send' do
redis = Redis.new
# params => {"username"=>"ArashM", "message"=>"Hi"}
redis.publish 'simple:chat', {username: params['username'], message: params['message']}.to_json
end
get '/subscribe' do
content_type 'text/event-stream'
redis = Redis.new
# For more information on streamin in sintara, see:
# http://www.sinatrarb.com/contrib/streaming.html
stream do |out|
# Listening to 'simple:chat' channel
redis.subscribe('simple:chat') do |on|
on.message do |event, data|
data = JSON.parse(data)
# There should be "data:" at the begining or it wont work. see:
# https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events
out.puts "data: {\"username\":\"#{data['username']}\",\"message\":\"#{data['message']}\"}\n" unless out.closed?
out.flush
out.errback do
logger.warn "lost connection"
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment