Class: Heathrow::EventBus
- Inherits:
-
Object
- Object
- Heathrow::EventBus
- Defined in:
- lib/heathrow/event_bus.rb
Overview
EventBus - Simple pub/sub system for inter-component communication
Usage:
bus = EventBus.instance
# Subscribe to events
bus.subscribe('message.new') { |data| puts "New message: #{data}" }
# Publish events
bus.publish('message.new', message_data)
# Unsubscribe
handler_id = bus.subscribe('message.new') { |data| ... }
bus.unsubscribe('message.new', handler_id)
Instance Attribute Summary collapse
-
#event_log ⇒ Object
readonly
Returns the value of attribute event_log.
-
#subscribers ⇒ Object
readonly
Returns the value of attribute subscribers.
Class Method Summary collapse
Instance Method Summary collapse
-
#clear ⇒ Object
Clear all subscribers (useful for testing).
-
#event_names ⇒ Object
Get all event names that have subscribers.
-
#initialize(logger = nil) ⇒ EventBus
constructor
A new instance of EventBus.
-
#log_events=(enabled) ⇒ Object
Enable/disable event logging.
- #log_events? ⇒ Boolean
-
#publish(event_name, data = nil) ⇒ Object
Publish an event.
-
#publish_async(event_name, data = nil) ⇒ Object
Publish event asynchronously (returns immediately).
-
#recent_events(count = 10) ⇒ Object
Get event log (last N events).
-
#subscribe(event_name, &block) ⇒ Object
Subscribe to an event Returns handler ID for later unsubscribing.
-
#subscriber_count(event_name) ⇒ Object
Get count of subscribers for an event.
-
#subscribers_for(event_name) ⇒ Object
Get all subscribers for an event.
-
#unsubscribe(event_name, handler_id) ⇒ Object
Unsubscribe from an event.
-
#unsubscribe_all(event_name) ⇒ Object
Unsubscribe all handlers for an event.
Constructor Details
#initialize(logger = nil) ⇒ EventBus
Returns a new instance of EventBus.
22 23 24 25 26 27 28 |
# File 'lib/heathrow/event_bus.rb', line 22 def initialize(logger = nil) @subscribers = Hash.new { |h, k| h[k] = {} } @event_log = [] @mutex = Mutex.new @logger = logger @next_id = 0 end |
Instance Attribute Details
#event_log ⇒ Object (readonly)
Returns the value of attribute event_log.
20 21 22 |
# File 'lib/heathrow/event_bus.rb', line 20 def event_log @event_log end |
#subscribers ⇒ Object (readonly)
Returns the value of attribute subscribers.
20 21 22 |
# File 'lib/heathrow/event_bus.rb', line 20 def subscribers @subscribers end |
Class Method Details
.instance ⇒ Object
166 167 168 |
# File 'lib/heathrow/event_bus.rb', line 166 def instance @instance ||= new end |
.reset_instance! ⇒ Object
170 171 172 |
# File 'lib/heathrow/event_bus.rb', line 170 def reset_instance! @instance = nil end |
Instance Method Details
#clear ⇒ Object
Clear all subscribers (useful for testing)
120 121 122 123 124 125 |
# File 'lib/heathrow/event_bus.rb', line 120 def clear @mutex.synchronize do @subscribers.clear @logger&.debug("EventBus: Cleared all subscribers") end end |
#event_names ⇒ Object
Get all event names that have subscribers
106 107 108 109 110 |
# File 'lib/heathrow/event_bus.rb', line 106 def event_names @mutex.synchronize do @subscribers.keys.reject { |k| @subscribers[k].empty? } end end |
#log_events=(enabled) ⇒ Object
Enable/disable event logging
135 136 137 |
# File 'lib/heathrow/event_bus.rb', line 135 def log_events=(enabled) @log_events = enabled end |
#log_events? ⇒ Boolean
139 140 141 |
# File 'lib/heathrow/event_bus.rb', line 139 def log_events? @log_events != false # Default to true end |
#publish(event_name, data = nil) ⇒ Object
Publish an event
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/heathrow/event_bus.rb', line 64 def publish(event_name, data = nil) handlers = nil @mutex.synchronize do handlers = @subscribers[event_name].values.dup log_event(event_name, data) end @logger&.debug("EventBus: Publishing '#{event_name}' to #{handlers.size} handler(s)") # Execute handlers outside the mutex to avoid deadlocks handlers.each do |handler| begin handler.call(data) rescue => e @logger&.error("EventBus: Error in handler for '#{event_name}': #{e.}") @logger&.error(e.backtrace.join("\n")) if @logger end end handlers.size end |
#publish_async(event_name, data = nil) ⇒ Object
Publish event asynchronously (returns immediately)
88 89 90 91 92 93 94 95 96 |
# File 'lib/heathrow/event_bus.rb', line 88 def publish_async(event_name, data = nil) Thread.new do begin publish(event_name, data) rescue => e @logger&.error("EventBus: Error in async publish of '#{event_name}': #{e.}") end end end |
#recent_events(count = 10) ⇒ Object
Get event log (last N events)
128 129 130 131 132 |
# File 'lib/heathrow/event_bus.rb', line 128 def recent_events(count = 10) @mutex.synchronize do @event_log.last(count) end end |
#subscribe(event_name, &block) ⇒ Object
Subscribe to an event Returns handler ID for later unsubscribing
32 33 34 35 36 37 38 39 |
# File 'lib/heathrow/event_bus.rb', line 32 def subscribe(event_name, &block) @mutex.synchronize do handler_id = generate_handler_id @subscribers[event_name][handler_id] = block @logger&.debug("EventBus: Subscribed to '#{event_name}' (handler #{handler_id})") handler_id end end |
#subscriber_count(event_name) ⇒ Object
Get count of subscribers for an event
113 114 115 116 117 |
# File 'lib/heathrow/event_bus.rb', line 113 def subscriber_count(event_name) @mutex.synchronize do @subscribers[event_name].size end end |
#subscribers_for(event_name) ⇒ Object
Get all subscribers for an event
99 100 101 102 103 |
# File 'lib/heathrow/event_bus.rb', line 99 def subscribers_for(event_name) @mutex.synchronize do @subscribers[event_name].keys end end |
#unsubscribe(event_name, handler_id) ⇒ Object
Unsubscribe from an event
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/heathrow/event_bus.rb', line 42 def unsubscribe(event_name, handler_id) @mutex.synchronize do if @subscribers[event_name].delete(handler_id) @logger&.debug("EventBus: Unsubscribed from '#{event_name}' (handler #{handler_id})") true else false end end end |
#unsubscribe_all(event_name) ⇒ Object
Unsubscribe all handlers for an event
54 55 56 57 58 59 60 61 |
# File 'lib/heathrow/event_bus.rb', line 54 def unsubscribe_all(event_name) @mutex.synchronize do count = @subscribers[event_name].size @subscribers.delete(event_name) @logger&.debug("EventBus: Unsubscribed all #{count} handlers from '#{event_name}'") count end end |