Class: Servus::Events::Bus

Inherits:
Object
  • Object
show all
Defined in:
lib/servus/events/bus.rb

Overview

Thread-safe event bus for registering and dispatching event handlers.

The Bus acts as a central registry that maps event names to their corresponding handler classes. It uses ActiveSupport::Notifications internally to provide instrumentation and thread-safe event dispatch.

Events are automatically instrumented and will appear in Rails logs with timing information, making it easy to monitor event performance.

Examples:

Registering a handler

class UserCreatedHandler < Servus::EventHandler
  handles :user_created
end

Servus::Events::Bus.register_handler(:user_created, UserCreatedHandler)

Retrieving handlers for an event

handlers = Servus::Events::Bus.handlers_for(:user_created)
handlers.each { |handler| handler.handle(payload) }

Instrumentation in logs

Bus.emit(:user_created, user_id: 123)
# Rails log: servus.events.user_created (1.2ms) {:user_id=>123}

See Also:

Class Method Summary collapse

Class Method Details

.clearvoid

This method returns an undefined value.

Clears all registered handlers and unsubscribes from notifications.

Useful for testing and development mode reloading.

Examples:

Bus.clear


102
103
104
105
106
107
108
109
# File 'lib/servus/events/bus.rb', line 102

def clear
  subscriptions.values.flatten.each do |subscription|
    ActiveSupport::Notifications.unsubscribe(subscription)
  end

  @handlers = nil
  @subscriptions = nil
end

.emit(event_name, payload) ⇒ void

This method returns an undefined value.

Emits an event to all registered handlers with instrumentation.

Uses ActiveSupport::Notifications to instrument the event, providing automatic timing and logging. The event will appear in Rails logs with duration and payload information.

Examples:

Bus.emit(:user_created, { user_id: 123, email: '[email protected]' })
# Rails log: servus.events.user_created (1.2ms) {:user_id=>123, :email=>"[email protected]"}

Parameters:

  • event_name (Symbol)

    the name of the event to emit

  • payload (Hash)

    the event payload to pass to handlers



90
91
92
# File 'lib/servus/events/bus.rb', line 90

def emit(event_name, payload)
  ActiveSupport::Notifications.instrument(notification_name(event_name), payload)
end

.handlers_for(event_name) ⇒ Array<Class>

Retrieves all registered handlers for a specific event.

Returns a duplicate array to prevent external modification of the internal handler registry.

Examples:

handlers = Bus.handlers_for(:user_created)
handlers.each { |handler| handler.handle(payload) }

Parameters:

  • event_name (Symbol)

    the name of the event

Returns:

  • (Array<Class>)

    array of handler classes registered for this event



73
74
75
# File 'lib/servus/events/bus.rb', line 73

def handlers_for(event_name)
  (handlers[event_name] || []).dup
end

.register_handler(event_name, handler_class) ⇒ Array

Registers a handler class for a specific event.

Multiple handlers can be registered for the same event, and they will all be invoked when the event is emitted. The handler is automatically subscribed to ActiveSupport::Notifications.

Handlers are typically registered automatically when EventHandler classes are loaded at boot time via the handles DSL method.

Examples:

Bus.register_handler(:user_created, UserCreatedHandler)

Parameters:

  • event_name (Symbol)

    the name of the event

  • handler_class (Class)

    the handler class to register

Returns:

  • (Array)

    the updated array of handlers for this event



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/servus/events/bus.rb', line 47

def register_handler(event_name, handler_class)
  handlers[event_name] ||= []
  handlers[event_name] << handler_class

  # Subscribe to ActiveSupport::Notifications
  subscription = ActiveSupport::Notifications.subscribe(notification_name(event_name)) do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    handler_class.handle(event.payload)
  end

  # Store subscription for cleanup
  subscriptions[event_name] ||= []
  subscriptions[event_name] << subscription
end