class Tom::Dispatcher

Public Class Methods

dispatch(env) click to toggle source

Dispatches this request to all adapters that registered for the route and then calls the merger for this route to compose a response

@param env [Array] A rack env object

@return [Array] Whatever {Tom::Dispatcher.merge} had to say

# File lib/dispatcher.rb, line 13
def self.dispatch(env)

  # 1. hit APIs. All at the same time. Oh, mygodd!
  Tom::Log.logger.info "#{env['REQUEST_METHOD'].upcase} #{env['REQUEST_URI']}"
  responses = parallel_adapter_dispatch(env)

  # 2. merge
  merged = merge(env, responses)

  # 3. ???
  Tom::Log.logger.info "-------------------------------------------------------"

  # 4. profit
  merged
end
merge(env, responses) click to toggle source

Takes a request (rack env) and a couple of responses generated by api adapters and composes a response for the client.

The merger used depends on the route.

@param env [Array] A rack env object

@return [Array] The merged result of all requests

made as an array of status code, headers and body, e.g.
[200, {}, "Hi!"]
# File lib/dispatcher.rb, line 40
def self.merge(env, responses)
  route, method = route_and_method(env)
  if merger = Tom::Routes.merger_for_route(route, method)
    Tom::Log.logger.info "Merging with:"
    Tom::Log.logger.info "  -> #{merger}"
    merged = merger.new.merge(env, responses)
  else
    merged = [404, {}, ""]
  end
  merged[1]["Adapters-Used"] = responses.keys.join(",")
  merged
end
route_and_method(env) click to toggle source

Extract the route/request uri and the method from a rack env

@param env [Hash] A rack env

@return [Array] Contains request_path, request_method as symbols

# File lib/dispatcher.rb, line 61
def self.route_and_method(env)
  [env["REQUEST_PATH"],
   env["REQUEST_METHOD"].downcase.to_sym]
end

Private Class Methods

parallel_adapter_dispatch(env) click to toggle source

Uses a EM::Synchrony::FiberIterator to call all adapters that registered for this route at the same time.

@param env [Hash] A rack env object

@return [Hash] Keys are the adapter classes, values are arrays of responses

they generated (the [status_code, headers, body] triplets)
# File lib/dispatcher.rb, line 75
def self.parallel_adapter_dispatch(env)
  responses = {}
  route, method = route_and_method(env)
  adapters = Tom::Routes.adapters_for_route(route, method)
  return responses if adapters.empty?

  Tom::Log.logger.info "Dispatching to:"
  EM::Synchrony::FiberIterator.new(adapters, adapters.count).map do |clazz|
    Tom::Log.logger.info "  -> #{clazz}"
    (responses[clazz] ||= []) <<  clazz.new.handle(env)
  end
  responses
end