Skip to content

Instantly share code, notes, and snippets.

@sgeorgi
Last active June 28, 2022 16:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sgeorgi/5664920 to your computer and use it in GitHub Desktop.
Save sgeorgi/5664920 to your computer and use it in GitHub Desktop.
Generating events as Resque/Redis.jobs and publishing them to a faye websocket on the client. This is untested, but copied off a working project's implementation
require ::File.expand_path('../config/environment', __FILE__)
require 'faye'
require 'resque/server'
Faye::WebSocket.load_adapter('thin')
use Faye::RackAdapter, mount: '/stream', timeout: 45, extensions: []
map '/resque' do
use Rack::Auth::Basic do |username, password|
[username, password] == ['hello', 'thisisdog']
end
run Resque::Server.new
end
run Rails.application

Pushing data from Server to the Client using Faye, a Resque-Job and some JS

EDIT: Forgot to mention that you need Faye's JS in your client, so just add

<%= javascript_include_tag :defaults, "http://localhost:3000/stream.js" %>

to your application.html.erb!

  1. Start server (and resque-worker) with rails s thin (and rake resque-work).
  2. Go to the index page of your Controller
  3. Open up a console and either fire up Events manually by calling Resque's perform action directly as
    rails c
    => PushEventJob.perform('my_events', 'hello', 'this is dog'
    
    or by queueing the Job and let the worker to the rest as
    rails c
    => Resque.enqueue(PushEventJob, 'my_events', 'hello', 'this is dog')
    
    or by using curl from the command line like
    curl http://localhost:3000/stream -d 'message={"channel":"/my_channel", \
    
       "data":"{\"title\":\"hello\",\"message\":\"this is dog\"}"}'` 
    
# add to Gemfile
gem 'faye'
gem 'thin'
gem 'resque'
function initializeMyEventSocket() {
var faye = new Faye.Client('http://localhost:3000/stream');
faye.subscribe("/my_channel", function (data) {
addEventToList(data.title, data.message)
});
}
function addEventToList(title, message) {
$('#events').prepend('<p><strong>' + title + ': </strong>' + message + '</p>');
}
<h3>Server Side Events</h3>
<div id='events'></div>
<script type="text/javascript">
$(document).ready(function () {
initializeMyEventSocket();
});
</script>
# app/models/my_event.rb
class MyEvent < ActiveRecord::Base
def as_json(options={})
{ title: title, message: message.chomp() }
end
end
# app/jobs/push_event_job.rb
class PushEventEJob
@queue = "default"
def self.perform(channel='my_channel', title, message)
data = MyEvent.new(title: title, message: message).to_json
SocketPusher.push(channel, data)
end
end
# app/models/socket_pusher.rb
require 'net/http'
class SocketPusher
# Serializes given input to JSON and pushes to the given channel
# The POST goes to this very same instance of Thin and is pushed to
# the connected clients via a Websocket
def self.push(channel, input)
message = { channel: channel, data: input }
uri = URI.parse('http://localhost:3000/stream') # "stream", as configured in config.ru
Net::HTTP.post_form(uri, message: message.to_json)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment