Skip to content

Commit

Permalink
Add Immutable Dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
dcsg committed Jul 14, 2017
1 parent 952730c commit 782115a
Show file tree
Hide file tree
Showing 4 changed files with 396 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/eventception.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'eventception/event'
require 'eventception/listener_handler'
require 'eventception/dispatcher'
require 'eventception/immutable_dispatcher'
require 'eventception/base_subscriber'
require 'eventception/version'
55 changes: 55 additions & 0 deletions lib/eventception/dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def listeners?

# Gets all listeners for the specific event sorted by descending priority.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# The event listeners for the specific event sorted by descending priority.
#
Expand All @@ -82,6 +86,10 @@ def listeners_for(event_name:)

# Checks whether are any registered listeners for the specific event.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# Boolean
#
Expand All @@ -96,16 +104,35 @@ def listeners_for?(event_name:)
# The event to listen on
# listener::
# The listener
# listener_method::
# The name of the method to be executed in the listener
# priority::
# The higher this value, the earlier an event listener will be triggered in the chain (defaults to 0)
#
# == Returns:
# Nil
#
def add_listener(event_name:, listener:, listener_method:, priority: 0)
event_listeners[event_name][priority] << ListenerHandler.new(listener, listener_method)
sorted.delete(event_name)

nil
end


# Removes an event listener from the specified events.
#
# == Parameters:
# event_name::
# The event to listen on
# listener::
# The listener
# listener_method::
# The name of the method to be executed in the listener
#
# == Returns:
# Nil
#
def remove_listener(event_name:, listener:, listener_method:)
return unless listeners_for?(event_name: event_name)

Expand All @@ -118,6 +145,8 @@ def remove_listener(event_name:, listener:, listener_method:)
end

event_listeners.delete(event_name) if listener_for_event.empty?

nil
end

# Add an event subscriber.
Expand All @@ -128,6 +157,9 @@ def remove_listener(event_name:, listener:, listener_method:)
# subscriber::
# The subscriber
#
# == Returns:
# Nil
#
def add_subscriber(subscriber:)
subscriber.subscribed_events.each do |event_subscribed|
add_listener(
Expand All @@ -137,8 +169,21 @@ def add_subscriber(subscriber:)
priority: event_subscribed[:priority] || 0,
)
end

nil
end

# Removes an event subscriber.
#
# The subscriber is asked for all the events he is interested in and added as a listener for these events.
#
# == Parameters:
# subscriber::
# The subscriber
#
# == Returns:
# Nil
#
def remove_subscriber(subscriber:)
subscriber.subscribed_events.each do |event_subscribed|
remove_listener(
Expand All @@ -147,6 +192,8 @@ def remove_subscriber(subscriber:)
listener_method: event_subscribed.fetch(:listener_method),
)
end

nil
end

protected
Expand All @@ -161,6 +208,9 @@ def remove_subscriber(subscriber:)
# event::
# The event
#
# == Returns:
# Nil
#
def do_dispatch(listeners:, event:)
listeners.each do |_priority, priority_listeners|
priority_listeners.each do |listener_handler|
Expand All @@ -181,8 +231,13 @@ def do_dispatch(listeners:, event:)
# event_name::
# The event name
#
# == Returns:
# Nil
#
def sort_listeners(event_name)
sorted[event_name] = event_listeners[event_name].sort_by { |key, _| -key }.to_h

nil
end
end
end
102 changes: 102 additions & 0 deletions lib/eventception/immutable_dispatcher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# @author Daniel Gomes <danielcesargomes@gmail.com>
module Eventception
class ImmutableDispatcher
private

attr_reader :dispatcher

public

# Creates an unmodifiable proxy for an event dispatcher.
#
# == Parameters:
# listeners::
# Array of event listeners
# subscribers::
# Array of event subscribers
#
# == Returns:
# Nil
#
def initialize(listeners: [], subscribers: [])
@dispatcher = Eventception::Dispatcher.new

listeners.each do |listener|
dispatcher.add_listener(
event_name: listener.fetch(:event_name),
listener: listener.fetch(:listener),
listener_method: listener.fetch(:listener_method),
priority: listener.fetch(:priority, 0),
)
end

subscribers.each { |subscriber| dispatcher.add_subscriber(subscriber: subscriber) }

nil
end

# Dispatches an event to all registered listeners.
#
# == Parameters:
# event_name::
# The name of the event to dispatch. The name of
# the event is the name of the method that is
# invoked on listeners.
# event::
# The event to pass to the event handlers/listeners
# If not supplied, an empty Event instance is created.
#
# == Returns:
# The Event.
#
def dispatch(event_name:, event: Eventception::Event.new)
dispatcher.dispatch(event_name: event_name, event: event)

event
end

# Gets all listeners sorted by descending priority.
#
# == Returns:
# All event listeners sorted by event_name and descending priority.
#
def listeners
dispatcher.listeners
end

# Checks whether are any registered listeners.
#
# == Returns:
# Boolean
#
def listeners?
dispatcher.listeners?
end

# Gets all listeners for the specific event sorted by descending priority.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# The event listeners for the specific event sorted by descending priority.
#
def listeners_for(event_name:)
dispatcher.listeners_for(event_name: event_name)
end

# Checks whether are any registered listeners for the specific event.
#
# == Parameters:
# event_name::
# The name of the event
#
# == Returns:
# Boolean
#
def listeners_for?(event_name:)
dispatcher.listeners_for?(event_name: event_name)
end
end
end
Loading

0 comments on commit 782115a

Please sign in to comment.