-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
bus.rb
96 lines (83 loc) · 2.36 KB
/
bus.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
# frozen_string_literal: true
require 'dry/events/constants'
module Dry
module Events
# Event bus
#
# An event bus stores listeners (callbacks) and events
#
# @api private
class Bus
# @!attribute [r] events
# @return [Hash] A hash with events registered within a bus
attr_reader :events
# @!attribute [r] listeners
# @return [Hash] A hash with event listeners registered within a bus
attr_reader :listeners
# Initialize a new event bus
#
# @param [Hash] events A hash with events
# @param [Hash] listeners A hash with listeners
#
# @api private
def initialize(events: EMPTY_HASH, listeners: LISTENERS_HASH.dup)
@listeners = listeners
@events = events
end
# @api private
def process(event_id, payload)
listeners[event_id].each do |listener, filter|
event = events[event_id].payload(payload)
if filter.(payload)
yield(event, listener)
end
end
end
# @api private
def publish(event_id, payload)
process(event_id, payload) do |event, listener|
listener.(event)
end
end
# @api private
def attach(listener, filter)
events.each do |id, event|
meth = event.listener_method
if listener.respond_to?(meth)
listeners[id] << [listener.method(meth), filter]
end
end
end
# @api private
def detach(listener)
listeners.each do |id, memo|
memo.each do |tuple|
current_listener, _ = tuple
listeners[id].delete(tuple) if current_listener.receiver.equal?(listener)
end
end
end
# @api private
def subscribe(event_id, filter, &block)
listeners[event_id] << [block, filter]
self
end
# @api private
def subscribed?(listener)
listeners.values.any? { |value| value.any? { |block, _| block.equal?(listener) } }
end
# @api private
def can_handle?(object_or_event_id)
case object_or_event_id
when String, Symbol
events.key?(object_or_event_id)
else
events
.values
.map(&:listener_method)
.any?(&object_or_event_id.method(:respond_to?))
end
end
end
end
end