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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
57
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
PDI: Como Alavancar Sua Carreira e Seu Negócio
marcelgsantos
0
120
瑠璃の宝石に学ぶ技術の声の聴き方 / 【劇場版】アニメから得た学びを発表会2026 #エンジニアニメ
mazrean
0
230
CursorとClaudeCodeとCodexとOpenCodeを実際に比較してみた
terisuke
1
400
「効かない!」依存性注入(DI)を活用したAPI Platformのエラーハンドリング奮闘記
mkmk884
0
320
PHP でエミュレータを自作して Ubuntu を動かそう
m3m0r7
PRO
2
180
Rethinking API Platform Filters
vinceamstoutz
0
11k
GNU Makeの使い方 / How to use GNU Make
kaityo256
PRO
16
5.6k
「話せることがない」を乗り越える 〜日常業務から登壇テーマをつくる思考法〜
shoheimitani
4
720
RSAが破られる前に知っておきたい 耐量子計算機暗号(PQC)入門 / Intro to PQC: Preparing for the Post-RSA Era
mackey0225
3
130
アーキテクチャモダナイゼーションとは何か
nwiizo
17
4.9k
実践CRDT
tamadeveloper
0
440
ネイティブアプリとWebフロントエンドのAPI通信ラッパーにおける共通化の勘所
suguruooki
0
260
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
260
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
260
Testing 201, or: Great Expectations
jmmastey
46
8.1k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
1
1.5k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
68
38k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
360
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
720
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
270
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
330
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
670
Building Adaptive Systems
keathley
44
3k
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?