-
Notifications
You must be signed in to change notification settings - Fork 54
/
events.rb
179 lines (172 loc) · 6.85 KB
/
events.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
require 'securerandom' # For AS::Notifications
require 'as/notifications'
require 'webmachine/events/instrumented_event'
module Webmachine
# {Webmachine::Events} implements the
# [ActiveSupport::Notifications](http://rubydoc.info/gems/activesupport/ActiveSupport/Notifications)
# instrumentation API. It delegates to the configured backend.
# The default backend is
# [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications).
#
# # Published events
#
# Webmachine publishes some internal events by default. All of them use
# the `wm.` prefix.
#
# ## `wm.dispatch` ({.instrument})
#
# The payload hash includes the following keys.
#
# * `:resource` - The resource class name
# * `:request` - A copy of the request object
# * `:code` - The response code
#
module Events
class << self
# The class that {Webmachine::Events} delegates all messages to.
# (default [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications))
#
# It can be changed to an
# [ActiveSupport::Notifications](http://rubydoc.info/gems/activesupport/ActiveSupport/Notifications)
# compatible backend early in the application startup process.
#
# @example
# require 'webmachine'
# require 'active_support/notifications'
#
# Webmachine::Events.backend = ActiveSupport::Notifications
#
# Webmachine::Application.new {|app|
# # setup application
# }.run
attr_accessor :backend
# Publishes the given arguments to all listeners subscribed to the given
# event name.
# @param name [String] the event name
# @example
# Webmachine::Event.publish('wm.foo', :hello => 'world')
def publish(name, *args)
backend.publish(name, *args)
end
# Instrument the given block by measuring the time taken to execute it
# and publish it. Notice that events get sent even if an error occurs
# in the passed-in block.
#
# If an exception happens during an instrumentation the payload will
# have a key `:exception` with an array of two elements as value:
# a string with the name of the exception class, and the exception
# message. (when using the default
# [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications)
# backend)
#
# @param name [String] the event name
# @param payload [Hash] the initial payload
#
# @example
# Webmachine::Events.instrument('wm.dispatch') do |payload|
# execute_some_method
#
# payload[:custom_payload_value] = 'important'
# end
def instrument(name, payload = {}, &block)
backend.instrument(name, payload, &block)
end
# Subscribes to the given event name.
#
# @note The documentation of this method describes its behaviour with the
# default backed [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications).
# It can change if a different backend is used.
#
# @overload subscribe(name)
# Subscribing to an {.instrument} event. The block arguments can be
# passed to {Webmachine::Events::InstrumentedEvent}.
#
# @param name [String, Regexp] the event name to subscribe to
# @yieldparam name [String] the event name
# @yieldparam start [Time] the event start time
# @yieldparam end [Time] the event end time
# @yieldparam event_id [String] the event id
# @yieldparam payload [Hash] the event payload
# @return [Object] the subscriber object (type depends on the backend implementation)
#
# @example
# # Subscribe to all 'wm.dispatch' events
# Webmachine::Event.subscribe('wm.dispatch') {|*args|
# event = Webmachine::Events::InstrumentedEvent.new(*args)
# }
#
# # Subscribe to all events that start with 'wm.'
# Webmachine::Event.subscribe(/wm\.*/) {|*args| }
#
# @overload subscribe(name)
# Subscribing to a {.publish} event.
#
# @param name [String, Regexp] the event name to subscribe to
# @yieldparam name [String] the event name
# @yieldparam *args [Array] the published arguments
# @return [Object] the subscriber object (type depends on the backend implementation)
#
# @example
# Webmachine::Event.subscribe('custom.event') {|name, *args|
# args #=> [obj1, obj2, {:num => 1}]
# }
#
# Webmachine::Event.publish('custom.event', obj1, obj2, {:num => 1})
#
# @overload subscribe(name, listener)
# Subscribing with a listener object instead of a block. The listener
# object must respond to `#call`.
#
# @param name [String, Regexp] the event name to subscribe to
# @param listener [#call] a listener object
# @return [Object] the subscriber object (type depends on the backend implementation)
#
# @example
# class CustomListener
# def call(name, *args)
# # ...
# end
# end
#
# Webmachine::Event.subscribe('wm.dispatch', CustomListener.new)
#
def subscribe(name, *args, &block)
backend.subscribe(name, *args, &block)
end
# Subscribe to an event temporarily while the block runs.
#
# @note The documentation of this method describes its behaviour with the
# default backed [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications).
# It can change if a different backend is used.
#
# The callback in the following example will be called for all
# "sql.active_record" events instrumented during the execution of the
# block. The callback is unsubscribed automatically after that.
#
# @example
# callback = lambda {|name, *args| handle_event(name, *args) }
#
# Webmachine::Events.subscribed(callback, 'sql.active_record') do
# call_active_record
# end
def subscribed(callback, name, &block)
backend.subscribed(callback, name, &block)
end
# Unsubscribes the given subscriber.
#
# @note The documentation of this method describes its behaviour with the
# default backed [AS::Notifications](http://rubydoc.info/gems/as-notifications/AS/Notifications).
# It can change if a different backend is used.
#
# @param subscriber [Object] the subscriber object (type depends on the backend implementation)
# @example
# subscriber = Webmachine::Event.subscribe('wm.dispatch') {|*args| }
#
# Webmachine::Event.unsubscribe(subscriber)
def unsubscribe(subscriber)
backend.unsubscribe(subscriber)
end
end
self.backend = AS::Notifications
end
end