Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Streaming APIs with Ruby

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Streaming APIs with Ruby

An introduction to RESTful streaming HTTP APIs and how to implement one with Rack::Stream

Avatar for Jerry Cheung

Jerry Cheung

June 04, 2012
Tweet

More Decks by Jerry Cheung

Other Decks in Programming

Transcript

  1. Static Web • page is fixed after render • server

    does all work • one request, one page Monday, June 4, 12
  2. AJAX Web • break pages into “pagelets” • dynamic updates

    inline • one request, N-pagelets Monday, June 4, 12
  3. App Web • browser not the only client • rich

    UX, native-feel, desktop parity Monday, June 4, 12
  4. Comet Web application model in which a long- held HTTP

    request allows a web server to push data to a browser, without the browser explicitly requesting it. Monday, June 4, 12
  5. server-side Web 1.0 JS server-side Web 2.0 API web, mobile,

    3rd party Web 3.0 Trend Monday, June 4, 12
  6. WebSockets var socket = new Websocket('ws://example.com/resource'); socket.onopen(function() { // connection

    established }); socket.onmessage(function(message) { console.log(message.data); }) socket.onclose(function() { // connection closing }); Monday, June 4, 12
  7. WebSocket • + simple interface • + web standard •

    - not available everywhere Monday, June 4, 12
  8. EventSource • + simple interface • + web standard •

    - not available everywhere • - unidirectional subset of WebSocket Monday, June 4, 12
  9. AJAX Long Polling • + available almost everywhere • -

    browser keeps long running connections • - extra book-keeping for reconnect, messages Monday, June 4, 12
  10. WebSocket Emulation • Firehose.io • socket.io • Pusher • Faye

    • flash sockets • more... Monday, June 4, 12
  11. Rack::Stream • rackable - works with Sinatra, Rails, rack middleware

    • simple interface - #chunk(message) • multi-transport - WebSocket, EventSource, Long-poll Monday, June 4, 12
  12. Rack-able require 'sinatra' use Rack::Stream get '/' do status 200

    headers 'Content-Type' => 'text/plain' "Hello World" end Monday, June 4, 12
  13. Rack-able require 'sinatra' use Rack::Stream get '/' do status 200

    headers 'Content-Type' => 'text/plain' "Hello World" end ‘chunked’ Transfer-Encoding Monday, June 4, 12
  14. Rack-able require 'sinatra' use Rack::Stream get '/' do status 200

    headers 'Content-Type' => 'text/plain' "Hello World" end ‘chunked’ Transfer-Encoding Response bodies streamed out to clients Monday, June 4, 12
  15. Stream to 100 require 'sinatra' use Rack::Stream # Starting... #

    0 # 1 # ... # 99 get '/hundred' do 100.times.each do |i| chunk(i) end "Starting..." end Monday, June 4, 12
  16. Stream to 100 require 'sinatra' use Rack::Stream # Starting... #

    0 # 1 # ... # 99 get '/hundred' do 100.times.each do |i| chunk(i) end "Starting..." end stream response bodies Monday, June 4, 12
  17. Stream to 100 require 'sinatra' use Rack::Stream # Starting... #

    0 # 1 # ... # 99 get '/hundred' do 100.times.each do |i| chunk(i) end "Starting..." end enqueue content to stream stream response bodies Monday, June 4, 12
  18. Persistent Connections • connection closes when there’s no data left

    • keep “chunking” data • don’t close the connection Monday, June 4, 12
  19. Chat class API < Grape::API # snip... resources :messages do

    get do after_open do # subscribe after_open b/c this runs # until the connection is closed redis.subscribe 'messages' do |on| on.message do |channel, msg| chunk msg end end end # snip... end post do redis.publish 'messages', params[:text] end end end Monday, June 4, 12
  20. Chat class API < Grape::API # snip... resources :messages do

    get do after_open do # subscribe after_open b/c this runs # until the connection is closed redis.subscribe 'messages' do |on| on.message do |channel, msg| chunk msg end end end # snip... end post do redis.publish 'messages', params[:text] end end end Define a resource Monday, June 4, 12
  21. Chat class API < Grape::API # snip... resources :messages do

    get do after_open do # subscribe after_open b/c this runs # until the connection is closed redis.subscribe 'messages' do |on| on.message do |channel, msg| chunk msg end end end # snip... end post do redis.publish 'messages', params[:text] end end end Define a resource create messages Monday, June 4, 12
  22. Chat class API < Grape::API # snip... resources :messages do

    get do after_open do # subscribe after_open b/c this runs # until the connection is closed redis.subscribe 'messages' do |on| on.message do |channel, msg| chunk msg end end end # snip... end post do redis.publish 'messages', params[:text] end end end Define a resource create messages stream new messages Monday, June 4, 12
  23. Compose with Rack map '/' do run Chat::Application end map

    '/messages' do use Rack::Stream run API end Rack::Stream + Grape Rails Monday, June 4, 12
  24. Manipulating Streams use Rack::Stream # outputs "HELLO WORLD" get '/'

    do before_chunk do |chunks| chunks.map(&:upcase) end chunk "world" "hello " end Monday, June 4, 12
  25. Roadmap • Currently only works with Thin • Additional transport

    handlers • Load and compatibility testing Monday, June 4, 12