Created
May 3, 2011 06:47
-
-
Save mrflip/952914 to your computer and use it in GitHub Desktop.
a way to make an asynchronous request in the middleware, and only proceed with the response when both the endpoint and our middleware's responses have completed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Barrier < EM::Synchrony::Multi | |
attr_accessor :env, :status, :headers, :body | |
def initialize env | |
super() | |
@env = env | |
@acb = env['async.callback'] | |
env['async.callback'] = self | |
callback do | |
@acb.call(post_process) | |
end | |
end | |
def pre_process | |
end | |
def call shb | |
status, headers, body = shb | |
return shb if status == Goliath::Connection::AsyncResponse.first | |
@status, @headers, @body = status, headers, body | |
succeed if finished? | |
end | |
def post_process | |
end | |
def finished? | |
super && @status | |
end | |
end | |
class AsyncAroundware | |
def initialize app, barrier_klass | |
@app = app | |
@barrier_klass = barrier_klass | |
end | |
def call(env, *args, &block) | |
barrier = @barrier_klass.new(env) | |
barrier.pre_process | |
barrier.call(@app.call(env)) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
$: << File.dirname(__FILE__)+'/../../lib' | |
require 'goliath' | |
require 'em-synchrony/em-http' | |
require 'yajl/json_gem' | |
require 'async_aroundware.rb' | |
# | |
# Here's a way to make an asynchronous request in the middleware, and only | |
# proceed with the response when both the endpoint and our middleware's | |
# responses have completed. | |
# | |
# To run this, start the 'sleepy.rb' server on port 9002: | |
# | |
# ./sleepy.rb -sv -p 9002 | |
# | |
# And then start the async_aroundware_demo_multi.rb server on port 9000: | |
# | |
# ./async_aroundware_demo_multi.rb -sv -p 9000 | |
# | |
# Now curl the async_aroundware_demo_multi: | |
# | |
# $ time curl 'http://127.0.0.1:9000/?delay_1=1.0&delay_2=1.5' | |
# {"results":{"sleep_2":[1304405129.793657,1.5,1.5003128051757812],"sleep_1":[1304405129.793349,1.0,1.000417947769165]},"errors":{}} | |
# | |
BASE_URL = 'http://localhost:9002/' | |
class MyBarrier < Barrier | |
def pre_process | |
add :sleep_1, EM::HttpRequest.new("#{BASE_URL}?delay=#{env.params['delay_1']}").aget | |
end | |
def post_process | |
results = { :results => { :sleep_2 => body }, :errors => {} } | |
responses[:callback].each{|name, resp| results[:results][name] = JSON.parse(resp.response) } | |
responses[:errback ].each{|name, err| results[:errors][name] = err.error } | |
[status, headers, JSON.generate(results)] | |
end | |
end | |
class AsyncAroundwareDemoMulti < Goliath::API | |
use Goliath::Rack::Params | |
use Goliath::Rack::Validation::NumericRange, {:key => 'delay_1', :default => 1.0, :max => 5.0, :min => 0.0, :as => Float} | |
use Goliath::Rack::Validation::NumericRange, {:key => 'delay_2', :default => 0.5, :max => 5.0, :min => 0.0, :as => Float} | |
# | |
use AsyncAroundware, MyBarrier | |
def response(env) | |
resp = EM::HttpRequest.new("#{BASE_URL}?delay=#{env.params['delay_2']}").get | |
[200, { }, JSON.parse(resp.response)] | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'goliath' | |
# Wait the amount of time given by the 'delay' parameter before responding (default 2.5, max 15.0). | |
class Sleepy < Goliath::API | |
use Goliath::Rack::Params | |
use Goliath::Rack::Validation::NumericRange, {:key => 'delay', :default => 2.5, :max => 15.0, :min => 0.0, :as => Float} | |
def response(env) | |
EM::Synchrony.sleep(env.params['delay']) | |
[ 200, | |
{ 'X-Sleepy-Delay' => env.params['delay'].to_s }, | |
[ env[:start_time], env.params['delay'], (Time.now.to_f - env[:start_time].to_f) ].inspect | |
] | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment