Class: DiscordRDA::EventBus

Inherits:
Object
  • Object
show all
Defined in:
lib/discord_rda/event/bus.rb

Overview

Event bus for publish-subscribe event handling. Routes events from Gateway to registered handlers.

Defined Under Namespace

Classes: Subscription

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(logger: nil) ⇒ EventBus

Initialize event bus

Parameters:

  • logger (Logger) (defaults to: nil)

    Logger instance



19
20
21
22
23
24
# File 'lib/discord_rda/event/bus.rb', line 19

def initialize(logger: nil)
  @logger = logger
  @handlers = {}
  @middleware = []
  @mutex = Mutex.new
end

Instance Attribute Details

#handlersHash<String, Array<EventHandler>> (readonly)

Returns Registered handlers.

Returns:

  • (Hash<String, Array<EventHandler>>)

    Registered handlers



9
10
11
# File 'lib/discord_rda/event/bus.rb', line 9

def handlers
  @handlers
end

#loggerLogger (readonly)

Returns Logger instance.

Returns:

  • (Logger)

    Logger instance



12
13
14
# File 'lib/discord_rda/event/bus.rb', line 12

def logger
  @logger
end

#middlewareArray<Middleware> (readonly)

Returns Global middleware.

Returns:



15
16
17
# File 'lib/discord_rda/event/bus.rb', line 15

def middleware
  @middleware
end

Instance Method Details

#event_typesArray<String>

Get all registered event types

Returns:

  • (Array<String>)

    Event types



110
111
112
# File 'lib/discord_rda/event/bus.rb', line 110

def event_types
  @handlers.keys
end

#has_handlers?(event_type) ⇒ Boolean

Check if event type has handlers

Parameters:

  • event_type (String, Symbol)

    Event type

Returns:

  • (Boolean)

    True if has handlers



117
118
119
120
# File 'lib/discord_rda/event/bus.rb', line 117

def has_handlers?(event_type)
  event_type = normalize_event_type(event_type)
  @handlers[event_type]&.any?
end

#off(event_type, handler) ⇒ void

This method returns an undefined value.

Unsubscribe a handler

Parameters:

  • event_type (String, Symbol)

    Event type

  • handler (EventHandler)

    Handler to remove



84
85
86
87
88
89
90
91
92
# File 'lib/discord_rda/event/bus.rb', line 84

def off(event_type, handler)
  event_type = normalize_event_type(event_type)

  @mutex.synchronize do
    @handlers[event_type]&.reject! { |sub| sub[:handler] == handler }
  end

  @logger&.debug('Unregistered handler', event: event_type)
end

#on(event_type, handler = nil, middleware: []) { ... } ⇒ Subscription

Subscribe to an event type

Parameters:

  • event_type (String, Symbol)

    Event type to subscribe to

  • handler (Proc, EventHandler) (defaults to: nil)

    Handler to call

  • middleware (Array<Middleware>) (defaults to: [])

    Middleware for this subscription

Yields:

  • Block to execute for event

Returns:



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/discord_rda/event/bus.rb', line 32

def on(event_type, handler = nil, middleware: [], &block)
  handler = block if block_given?
  handler = EventHandler.new(handler) unless handler.is_a?(EventHandler)

  event_type = normalize_event_type(event_type)

  @mutex.synchronize do
    @handlers[event_type] ||= []
    @handlers[event_type] << { handler: handler, middleware: middleware }
  end

  @logger&.debug('Registered handler', event: event_type)

  Subscription.new(self, event_type, handler)
end

#once(event_type, handler = nil) { ... } ⇒ Subscription

Subscribe to an event once

Parameters:

  • event_type (String, Symbol)

    Event type

  • handler (Proc, EventHandler) (defaults to: nil)

    Handler

Yields:

  • Block to execute

Returns:



53
54
55
56
57
58
59
60
61
# File 'lib/discord_rda/event/bus.rb', line 53

def once(event_type, handler = nil, &block)
  handler = block if block_given?
  wrapped_handler = proc do |event|
    handler.call(event)
    :unsubscribe
  end

  on(event_type, wrapped_handler)
end

#publish(event_type, event) ⇒ void

This method returns an undefined value.

Publish an event to all subscribers

Parameters:

  • event_type (String, Symbol)

    Event type

  • event (Event)

    Event object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/discord_rda/event/bus.rb', line 67

def publish(event_type, event)
  event_type = normalize_event_type(event_type)
  subscriptions = @mutex.synchronize { @handlers[event_type]&.dup || [] }

  return if subscriptions.empty?

  @logger&.debug('Publishing event', type: event_type, handler_count: subscriptions.length)

  subscriptions.each do |sub|
    dispatch_with_middleware(sub[:handler], event, sub[:middleware])
  end
end

#unuse(middleware) ⇒ void

This method returns an undefined value.

Remove global middleware

Parameters:

  • middleware (Middleware)

    Middleware to remove



104
105
106
# File 'lib/discord_rda/event/bus.rb', line 104

def unuse(middleware)
  @middleware.delete(middleware)
end

#use(middleware) ⇒ void

This method returns an undefined value.

Add global middleware

Parameters:



97
98
99
# File 'lib/discord_rda/event/bus.rb', line 97

def use(middleware)
  @middleware << middleware
end

#wait_for(event_type, timeout: nil) { ... } ⇒ Event?

Wait for an event (async)

Parameters:

  • event_type (String, Symbol)

    Event type to wait for

  • timeout (Float) (defaults to: nil)

    Timeout in seconds

Yields:

  • Block to match event

Returns:

  • (Event, nil)

    Event or nil if timeout



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/discord_rda/event/bus.rb', line 127

def wait_for(event_type, timeout: nil, &block)
  Async::Condition.new.tap do |condition|
    handler = on(event_type) do |event|
      if block.nil? || block.call(event)
        condition.signal(event)
        :unsubscribe
      end
    end

    timer = Async do
      sleep(timeout) if timeout
      condition.signal(nil)
    end if timeout

    result = condition.wait
    timer&.stop
    result
  end
end