Permalink
Browse files

Refactoring async_aroundware, Part I. in ResponseReceiver, the defaul…

…t pre_process returns Goliath::Connection::AsyncResponse; env is an attr_reader not attr_accessor; in examples/async_aroundware_demo.rb added a missing include. Otherwise, this commit is largely cosmetic.
  • Loading branch information...
1 parent 50fcd4d commit 72435e01c88a51fa45202827b27c91f4b08f42ed Philip (flip) Kromer committed Jul 30, 2011
@@ -2,6 +2,7 @@
$: << File.dirname(__FILE__)+'/../lib'
require 'goliath'
+require 'goliath/synchrony/response_receiver'
require 'em-synchrony/em-http'
require 'yajl/json_gem'
@@ -1,55 +1,78 @@
module Goliath
module Rack
class AsyncAroundware
- # Create a new AsyncAroundware
+ include Goliath::Rack::Validator
+
+ # Called by the framework to create the middleware. Any extra args passed
+ # to the use statement are sent to each response_receiver_klass as it is created.
#
# @example
# class MyResponseReceiver < Goliath::Rack::MultiReceiver
+ # def initialize(env, aq)
+ # @awesomeness_quotient = aq
+ # super(env)
+ # end
# # ... define pre_process and post_process ...
# end
#
- # class AsyncAroundwareDemoMulti < Goliath::API
- # use Goliath::Rack::AsyncAroundware, MyResponseReceiver
+ # class AwesomeApiWithShortening < Goliath::API
+ # use Goliath::Rack::AsyncAroundware, MyResponseReceiver, 3
# # ... stuff ...
# end
#
# @param app [#call] the downstream app
# @param response_receiver_klass a class that quacks like a
# Goliath::Rack::ResponseReceiver and an EM::Deferrable
# @param *args [Array] extra args to pass to the response_receiver
+ # @return [Goliath::Rack::AsyncMiddleware]
def initialize app, response_receiver_klass, *args
@app = app
@response_receiver_klass = response_receiver_klass
@response_receiver_args = args
end
+ # This coordinates a response_receiver to process a request. We hook the
+ # response_receiver in the middle of the async_callback chain:
+ # * send the downstream response to the barrier, whether received directly
+ # from @app.call or via async callback
+ # * have the upstream callback chain be invoked when the response_receiver completes
#
+ # @param env [Goliath::Env] The goliath environment
+ # @return [Array] The [status_code, headers, body] tuple
def call(env)
response_receiver = new_response_receiver(env)
- # put response_receiver in the middle of the async_callback chain:
- # * save the old callback chain;
- # * put the response_receiver in as the new async_callback;
- # * when the response_receiver completes, invoke the old callback chain
- async_callback = env['async.callback']
- env['async.callback'] = response_receiver
- response_receiver.callback{ do_postprocess(env, async_callback, response_receiver) }
- response_receiver.errback{ do_postprocess(env, async_callback, response_receiver) }
+ hook_into_callback_chain(env, response_receiver)
- response_receiver.pre_process
+ response_receiver_resp = response_receiver.pre_process
- response_receiver.call(@app.call(env))
+ downstream_resp = @app.call(env)
+ response_receiver.call(downstream_resp)
end
+ # Generate a response_receiver to process the request, using request env & any args
+ # passed to this Response_ReceiverMiddleware at creation
+ #
+ # @param env [Goliath::Env] The goliath environment
+ # @return [Goliath::Rack::AsyncResponse_Receiver] The response_receiver to process this request
def new_response_receiver(env)
@response_receiver_klass.new(env, *@response_receiver_args)
end
- include Goliath::Rack::Validator
+ # put response_receiver in the middle of the async_callback chain:
+ # * save the old callback chain;
+ # * have the downstream callback send results to the response_receiver (possibly
+ # completing it)
+ # * set the old callback chain to fire when the response_receiver completes
+ def hook_into_callback_chain(env, response_receiver)
+ async_callback = env['async.callback']
+ env['async.callback'] = response_receiver
+ response_receiver.callback{ do_postprocess(env, async_callback, response_receiver) }
+ response_receiver.errback{ do_postprocess(env, async_callback, response_receiver) }
+ end
+
def do_postprocess(env, async_callback, response_receiver)
- Goliath::Rack::Validator.safely(env) do
- async_callback.call(response_receiver.post_process)
- end
+ safely(env){ async_callback.call(response_receiver.post_process) }
end
end
end
@@ -1,19 +1,23 @@
module Goliath
module Synchrony
- #
- # FIXME: generalize this to work with any deferrable
module ResponseReceiver
- attr_accessor :env, :status, :headers, :body
+ # The request environment, set in the initializer
+ attr_reader :env
+ # The response, set by the BarrierMiddleware's downstream
+ attr_accessor :status, :headers, :body
# Override this method in your middleware to perform any preprocessing
- # (launching a deferred request, perhaps)
+ # (launching a deferred request, perhaps).
+ #
+ # @return [Array] array contains [status, headers, body]
def pre_process
+ Goliath::Connection::AsyncResponse
end
- # Override this method in your middleware to perform any postprocessing. This
- # will only be invoked when the deferrable and the response have been
- # received.
+ # Override this method in your middleware to perform any postprocessing.
+ # This will only be invoked when all deferred requests (including the
+ # response) have completed.
#
# @return [Array] array contains [status, headers, body]
def post_process

0 comments on commit 72435e0

Please sign in to comment.