Explore >> Select a destination


You are here

weblog.raganwald.com
| | www.blackbytes.info
18.2 parsecs away

Travel
| | What are Ruby blocks and how do they work? What about Ruby procs & lambdas? What are the differences between these? Find the answers in this post!
| | tenderlovemaking.com
39.1 parsecs away

Travel
| | TL;DR: Rack API is poor when you consider streaming response bodies. class FooApplication class ErbPage def to_a head = "the head tag" sleep(2) body = "the body tag" sleep(2) [head, body] end end def call(env) [200, {}, ErbPage.new.to_a] end end class FakeRack def serve(application) status, headers, body = application.call({}) p :status => status p :headers => headers body.each do |string| p string end body.close if body.respond_to?(:close) end end app = FooApplication.new rack = FakeRack.new rack.serve app $ time ruby foo.rb {:status=>200} {:headers=>{}} "the head tag" "the body tag" real 0m4.008s user 0m0.003s sys 0m0.003s class ResponseTimer def initialize(app) @app = app end def call(env) now = Time.now status, headers, body = @app.call(env) headers['X-Response-Took'] = Time.now - now [status, headers, body] end end app = FooApplication.new timer = ResponseTimer.new app rack = FakeRack.new rack.serve timer $ time ruby foo.rb {:status=>200} {:headers=>{"X-Response-Took"=>3.999937}} "the head tag" "the body tag" real 0m4.010s user 0m0.004s sys 0m0.004s class FooApplication class ErbPage def each head = "the head tag" yield head sleep(2) body = "the body tag" yield body sleep(2) end end def call(env) [200, {}, ErbPage.new] end end $ time ruby foo.rb {:status=>200} {:headers=>{"X-Response-Took"=>1.1e-05}} "the head tag" "the body tag" real 0m4.032s user 0m0.027s sys 0m0.016s class ResponseTimer def initialize(app) @app = app end def call(env) now = Time.now status, headers, body = @app.call(env) newbody = [] body.each { |str| newbody << str } headers['X-Response-Took'] = Time.now - now [status, headers, newbody] end end class ResponseTimer class TimerProxy def initialize(body) @now = Time.now @body = body end def close @body.close if @body.respond_to?(:close) $stderr.puts({'X-Response-Took' => (Time.now - @now)}) end def each(&block) @body.each(&block) end end def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) [status, headers, TimerProxy.new(body)] end end $ time ruby foo.rb {:status=>200} {:headers=>{}} "the head tag" "the body tag" {"X-Response-Took"=>4.000268} real 0m4.044s user 0m0.029s sys 0m0.015s class ResponseTimer def initialize(app) @app = app end def call(env) status, headers, body = @app.call(env) body.extend(Module.new { now = Time.now define_method(:close) do super if defined?(super) $stderr.puts({'X-Response-Took' => (Time.now - now)}) end }) [status, headers, body] end end class EndOfLife attr_reader :callbacks def initialize(app) @app = app @callbacks = [] end def call(env) status, headers, body = @app.call(env) body.extend(Module.new { attr_accessor :eol def close super if defined?(super) eol.callbacks.each { |cb| cb.call } end }) body.eol = self [status, headers, body] end end app = FooApplication.new eol = EndOfLife.new app eol.callbacks << lambda { puts "it finished!" } rack = FakeRack.new rack.serve eol Edit: I just noticed that Rack contains a "timer" middleware similar to the one I've implemented in this blog post. You can view the broken middleware here.
| | patshaughnessy.net
18.3 parsecs away

Travel
| |
| | robrace.dev
224.5 parsecs away

Travel
| A response to building a Twitter clone with Rails, CableReady, and StimulusReflex