Class: Goliath::Rack::BarrierAroundwareFactory

Inherits:
SimpleAroundwareFactory show all
Includes:
Validator
Defined in:
lib/goliath/rack/barrier_aroundware_factory.rb

Overview

Include this to enable middleware that can perform pre- and post-processing, orchestrating multiple concurrent requests.

For internal reasons, you can’t do the following as you would in Rack:

def call(env)
  # ... do pre-processing
  status, headers, body = @app.call(env)
  new_body = make_totally_awesome(body) ## !! BROKEN !!
  [status, headers, new_body]
end

This class creates an “aroundware” helper to do that kind of processing. Goliath proceeds asynchronously, but will still “unwind” the request by walking up the callback chain. Delegating out to the aroundware also lets you carry state around – the ban on instance variables no longer applies, as each aroundware is unique per request.

The strategy here is similar to that in EM::Multi. Figuring out what goes on there will help you understand this.

Instance Method Summary collapse

Methods included from Validator

safely, validation_error

Methods inherited from SimpleAroundwareFactory

#call, #final_response?, #initialize, #new_aroundware

Constructor Details

This class inherits a constructor from Goliath::Rack::SimpleAroundwareFactory

Instance Method Details

#hook_into_callback_chain(env, aroundware) ⇒ Object

Put aroundware in the middle of the async_callback chain:

  • save the old callback chain;

  • have the downstream callback send results to the aroundware (possibly completing it)

  • set the old callback chain to fire when the aroundware completes



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/goliath/rack/barrier_aroundware_factory.rb', line 38

def hook_into_callback_chain(env, aroundware)
  async_callback = env['async.callback']

  # The response from the downstream app is accepted by the aroundware...
  downstream_callback = Proc.new do |resp|
    safely(env){ aroundware.accept_response(:downstream_resp, true, resp) }
  end

  # .. but the upstream chain is only invoked when the aroundware completes
  invoke_upstream_chain = Proc.new do
    new_resp = safely(env){ aroundware.post_process }
    async_callback.call(new_resp)
  end

  env['async.callback'] = downstream_callback
  aroundware.add_to_pending(:downstream_resp)
  aroundware.callback(&invoke_upstream_chain)
  aroundware.errback(&invoke_upstream_chain)
end