Class: Philiprehberger::EventEmitter::Emitter

Inherits:
Object
  • Object
show all
Includes:
History, Invoker, ListenerStore
Defined in:
lib/philiprehberger/event_emitter/emitter.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(history_size: 0) ⇒ Emitter

Returns a new instance of Emitter.



13
14
15
16
17
18
19
20
21
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 13

def initialize(history_size: 0)
  @listeners = {}
  @wildcard_listeners = []
  @mutex = Mutex.new
  @on_error = nil
  @max_listeners = 10
  @history_size = history_size
  @history = []
end

Instance Attribute Details

#max_listenersObject

Returns the value of attribute max_listeners.



10
11
12
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 10

def max_listeners
  @max_listeners
end

#on_error=(value) ⇒ Object (writeonly)

Sets the attribute on_error

Parameters:

  • value

    the value to set the attribute on_error to.



11
12
13
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 11

def on_error=(value)
  @on_error = value
end

Instance Method Details

#emit(event, *args, **kwargs) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 41

def emit(event, *args, **kwargs)
  timestamp = Time.now
  record_history(event, args, kwargs, timestamp)
  all_entries = collect_entries(event)
  return false if all_entries.empty?

  meta = EventMetadata.new(event_name: event, timestamp: timestamp)
  invoke_entries(all_entries, args, kwargs, event, meta)
  true
end

#emit_async(event, *args, **kwargs) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 52

def emit_async(event, *args, **kwargs)
  timestamp = Time.now
  record_history(event, args, kwargs, timestamp)
  all_entries = collect_entries(event)
  return [] if all_entries.empty?

  meta = EventMetadata.new(event_name: event, timestamp: timestamp)
  spawn_listener_threads(all_entries, args, kwargs, event, meta)
end

#event_namesObject



129
130
131
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 129

def event_names
  @mutex.synchronize { @listeners.keys }
end

#event_stats(event) ⇒ Hash

Summary of registered listeners for an event, including wildcard matches. Useful for diagnostics: counts exact vs. wildcard listeners, one-shot listeners, and compares against the configured ceiling.

Parameters:

  • event (String, Symbol)

    the event name

Returns:

  • (Hash)

    :listeners, :once_listeners, :wildcards, :max_listeners



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 111

def event_stats(event)
  @mutex.synchronize do
    exact = @listeners[event] || []
    wildcards = @wildcard_listeners.select { |e| Pattern.match?(e[:pattern], event.to_s) }
    {
      listeners: exact.size + wildcards.size,
      once_listeners: exact.count { |e| e[:once] } + wildcards.count { |e| e[:once] },
      wildcards: wildcards.size,
      max_listeners: @max_listeners
    }
  end
end

#listener_count(event) ⇒ Object



101
102
103
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 101

def listener_count(event)
  @mutex.synchronize { (@listeners[event] || []).size }
end

#listeners(event) ⇒ Object



95
96
97
98
99
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 95

def listeners(event)
  @mutex.synchronize do
    (@listeners[event] || []).map { |entry| entry[:block] }
  end
end

#off(event, &block) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 84

def off(event, &block)
  @mutex.synchronize do
    if Pattern.wildcard?(event.to_s)
      remove_wildcard_listener(event, block)
    else
      remove_exact_listener(event, block)
    end
  end
  self
end

#on(event, priority: 0, replay: false, metadata: false, &block) ⇒ Object

Raises:

  • (ArgumentError)


23
24
25
26
27
28
29
30
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 23

def on(event, priority: 0, replay: false, metadata: false, &block)
  raise ArgumentError, 'block required' unless block

  entry = { block: block, once: false, priority: priority, metadata:  }
  register_listener(event, entry)
  replay_history(event, entry) if replay
  self
end

#once(event, priority: 0, replay: false, metadata: false, &block) ⇒ Object

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 32

def once(event, priority: 0, replay: false, metadata: false, &block)
  raise ArgumentError, 'block required' unless block

  entry = { block: block, once: true, priority: priority, metadata:  }
  register_listener(event, entry, check_max: false)
  replay_history(event, entry) if replay
  self
end

#remove_all_listeners(event = nil) ⇒ Object



124
125
126
127
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 124

def remove_all_listeners(event = nil)
  @mutex.synchronize { clear_listeners(event) }
  self
end

#wait(event, timeout: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/philiprehberger/event_emitter/emitter.rb', line 62

def wait(event, timeout: nil)
  mutex = Mutex.new
  cond = ConditionVariable.new
  payload = nil
  fired = false
  handler = lambda do |*args, **_kwargs|
    mutex.synchronize do
      next if fired

      payload = args
      fired = true
      cond.signal
    end
  end
  once(event, &handler)
  mutex.synchronize { cond.wait(mutex, timeout) unless fired }
  return payload if fired

  off(event, &handler)
  nil
end