Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Real-Time HTML5 and Ruby
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Luigi Ray-Montanez
March 24, 2012
Programming
660
3
Share
Real-Time HTML5 and Ruby
Presented at RubyNation on March 24, 2012.
Luigi Ray-Montanez
March 24, 2012
More Decks by Luigi Ray-Montanez
See All by Luigi Ray-Montanez
A Decade under the Influence
luigi
0
59
Building Upworthy on Rails
luigi
1
200
You'll Never Believe Which Web Framework Powers Upworthy
luigi
0
11k
Server-Sent Events at Realtime Conf 2012
luigi
4
600
Developer Happiness & MongoDB
luigi
2
490
Other Decks in Programming
See All in Programming
【26新卒研修資料】TDD実装演習
dip_tech
PRO
0
140
リセットCSSを1行消したらアクセシビリティが向上した話
pvcresin
3
380
WebAssembly を読み込むベストプラクティス 2026年春版 / Best Practices for Loading WebAssembly (Spring 2026)
petamoriken
5
1k
[RubyKaigi 2026] Require Hooks
palkan
1
270
AIエージェントで業務改善してみた
taku271
0
550
When benchmarks go bad - what I learned from measuring performance wrong
hollycummins
0
240
AI時代のPhpStorm最新事情 #phpcon_odawara
yusuke
0
240
Surviving Black Friday: 329 billion requests with Falcon!
ioquatix
0
2.4k
AIベース静的検査器の偽陽性率を抑える工夫3選
orgachem
PRO
4
380
PHPでローカル環境用のSSL/TLS証明書を発行することはできるのか? #phpconkagawa
akase244
0
270
Liberating Ruby's Parser from Lexer Hacks
ydah
2
2.4k
Making the RBS Parser Faster
soutaro
0
640
Featured
See All Featured
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
280
Leo the Paperboy
mayatellez
7
1.7k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
180
Exploring anti-patterns in Rails
aemeredith
3
340
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
910
Optimising Largest Contentful Paint
csswizardry
37
3.7k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
0
300
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.4k
Transcript
Real-Time HTML5 and Ruby Luigi Montanez RubyNation 2012
Overview Part 1 - Real-time HTML5 Technologies Part 2 -
EventMachine Part 3 - Ruby frameworks
tl;dw You can do this stu! in Ruby, you don’t
need Node.js.
Part 1: Real-Time HTML5 Technologies
The Enemy: Page Refreshing
“Classic” Solutions AJAX AJAX Polling COMET (Long Polling)
“Classic” Solutions AJAX AJAX Polling COMET (Long Polling)
WebSockets TCP Socket between browser and server Bi-directional Remains open
until explicitly closed
In the Browser var connection = new WebSocket('ws://example.com/echo'); connection.onopen =
function () { connection.send('Ping'); }; connection.onerror = function (error) { // handle error }; connection.onmessage = function (e) { console.log('Server said: ' + e.data); }; connection.onclose = function () { // ensure you expected a close };
Just TCP A lower level than HTTP Developer de"nes protocol
Support XMPP, IRC, AMQP, VNC Some proxy servers not compatible
No JS Poly!ll Flash-based fallback Socket.IO falls back using di!erent
methods
Bi-directional communication usually overkill.
Server-Sent Events Forgotten little brother of WebSockets Downstream, server to
browser push Just HTTP Browser handles reconnections Pure JS Poly"ll by Remy Sharp
In the Browser var source = new EventSource('/stream'); source.addEventListener('message', function(e)
{ console.log(e.data); }); source.addEventListener('open', function(e) { ... }); source.addEventListener('error', function(e) { ... });
Data data: first line\n data: second line\n\n --- data: {\n
data: "msg": "hello world",\n data: "id": 12345\n data: }\n\n source.addEventListener('message', function(e) { var data = JSON.parse(e.data); console.log(data.id, data.msg); });
Data IDs and Events id: 12345\n data: AAPL\n data: 572.44\n\n
--- data: {"msg": "First message"}\n\n event: userlogon\n data: {"username": "John123"}\n\n event: update\n data: {"username": "John123", "emotion": "happy"}\n\n source.addEventListener('userlogon', function(e) { ... source.addEventListener('update', function(e) { ...
Part 2: EventMachine
Why EM? Many concurrent, long-held connections Addresses the C10K Problem
Can’t use Rails or Rack to support WebSockets and Server-Sent Events
Reactor Pattern Single-threaded event loop listens to many sources Dispatches
synchronous work to handlers Handlers report when done
Timebomb require 'eventmachine' EM.run do EM.add_timer(5) do puts "BOOM" EM.stop_event_loop
end EM.add_periodic_timer(1) do puts "Tick" end end $ ruby timer.rb Tick Tick Tick Tick BOOM
Other Constructs EM#next_tick EM#defer EM::Deferrable EM::Queue EM::Channel
Problem: Pyramid Code or Callback Spaghetti
Tip of the Pyramid EventMachine.run { page = EventMachine::HttpRequest.new('http://example.com/').get page.errback
{ p "Google is down! terminate?" } page.callback { about = EventMachine::HttpRequest.new('http://example2.com').get about.callback { # callback nesting, ad infinitum } about.errback { # error-handling code } } }
EM::Synchrony Ruby 1.9 Fibers Abstracts away callbacks and errbacks Code
looks synchronous but is actually asynchronous
EM + Fiber def http_get(url) f = Fiber.current http =
EM::HttpRequest.new(url).get # resume fiber once http call is done http.callback { f.resume(http) } http.errback { f.resume(http) } return Fiber.yield end EM.run do Fiber.new{ page = http_get('http://www.google.com/') puts "Fetched page: #{page.response_header.status}" if page page = http_get('http://www.google.com/search?q=eventmachine') puts "Fetched page 2: #{page.response_header.status}" end }.resume end
EM::Synchrony::Multi EventMachine.synchrony do multi = EventMachine::Synchrony::Multi.new multi.add :a, EventMachine::HttpRequest.new(uri1).aget multi.add
:b, EventMachine::HttpRequest.new(uri2).apost multi.add :c, EventMachine::HttpRequest.new(uri3).aget res = multi.perform p "Look ma, no callbacks, and parallel HTTP requests!" p res EventMachine.stop end
Part 3: Ruby Frameworks
All built on top of EventMachine
Servers Thin Rainbows!
Cramp Built by Pratik Naik, “lifo” http://cramp.in Supports Fibers $
cramp new myapp
Server-Sent Events class TimeAction < Cramp::Action self.transport = :sse on_start
:send_latest_time periodic_timer :send_latest_time, :every => 2 def send_latest_time data = {'time' => Time.now.to_i}.to_json render data end end
Goliath Built by Ilya Grigorik http://goliath.io Supports EM::Synchrony Both a
server and a framework
Goliath App class Websocket < Goliath::API use Goliath::Rack::Favicon, ‘favicon.ico') map
'/ws', WebsocketEndPoint end
WebSocket Endpoint class WebsocketEndPoint < Goliath::WebSocket def on_open(env) env.logger.info("WS OPEN")
env['subscription'] = env.channel.subscribe { |m| env.stream_send(m) } end def on_message(env, msg) env.logger.info("WS MESSAGE: #{msg}") env.channel << msg end def on_close(env) env.logger.info("WS CLOSED") env.channel.unsubscribe(env['subscription']) end def on_error(env, error) env.logger.error error end end
Frameworks AsyncRack Cramp Faye::WebSocket Goliath
Caveats Separate app Ports vs. Paths Automated Testing
Credits HTML5 Rocks Ilya Grigorik Dan Sinclair Peepcode
Questions?