Class: Coach::Handler

Inherits:
Object
  • Object
show all
Defined in:
lib/coach/handler.rb

Constant Summary collapse

STATUS_CODE_FOR_EXCEPTIONS =
0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(middleware, config = {}) ⇒ Handler

Returns a new instance of Handler.



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/coach/handler.rb', line 12

def initialize(middleware, config = {})
  @config = config
  if middleware.is_a?(String)
    @name = middleware
  else
    @middleware = middleware
    @name = middleware.name
    # This triggers validation of the middleware chain, to raise any errors early on.
    root_item
  end
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/coach/handler.rb', line 10

def name
  @name
end

Instance Method Details

#build_request_chain(sequence, context) ⇒ Object

Given a middleware sequence, filter out items not applicable to the current request, and set up a chain of instantiated middleware objects, ready to serve a request.



71
72
73
74
75
# File 'lib/coach/handler.rb', line 71

def build_request_chain(sequence, context)
  sequence.reverse.reduce(nil) do |successor, item|
    item.build_middleware(context, successor)
  end
end

#build_sequence(item, context) ⇒ Object

Traverse the middlware tree to build a linear middleware sequence, containing only middlewares that apply to this request.



60
61
62
63
64
65
66
# File 'lib/coach/handler.rb', line 60

def build_sequence(item, context)
  sequence = item.middleware.middleware_dependencies.map do |child_item|
    build_sequence(child_item.set_parent(item), context)
  end

  dedup_sequence([*sequence, item].flatten)
end

#call(env) ⇒ Object

The Rack interface to handler - builds a middleware chain based on the current request, and invokes it.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/coach/handler.rb', line 28

def call(env)
  context = { request: ActionDispatch::Request.new(env) }
  sequence = build_sequence(root_item, context)
  chain = build_request_chain(sequence, context)

  event = build_event(context)

  publish("start_handler.coach", event.dup)
  instrument("finish_handler.coach", event) do
    response = chain.instrument.call
  rescue StandardError => e
    raise
  ensure
    # We want to populate the response and metadata fields after the middleware
    # chain has completed so that the end of the instrumentation can see them. The
    # simplest way to do this is pass the event by reference to ActiveSupport, then
    # modify the hash to contain this detail before the instrumentation completes.
    #
    # This way, the last finish_handler.coach event will have all the details.
    status = response.try(:first) || STATUS_CODE_FOR_EXCEPTIONS
    event.merge!(
      response: {
        status: status,
        exception: e,
      }.compact,
      metadata: context.fetch(:_metadata, {}),
    )
  end
end

#inspectObject



77
78
79
# File 'lib/coach/handler.rb', line 77

def inspect
  "#<Coach::Handler[#{name}]>"
end