Skip to content

Commit

Permalink
feat: support custom options on event and destinations (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmad-elassuty authored Feb 2, 2021
1 parent 2e36178 commit 742b8d5
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 47 deletions.
25 changes: 12 additions & 13 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
PATH
remote: .
specs:
event_router (0.2.0)
event_router (0.3.0)
activesupport

GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.3.2)
activesupport (6.1.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
ast (2.4.1)
byebug (11.1.3)
coderay (1.1.3)
concurrent-ruby (1.1.7)
concurrent-ruby (1.1.8)
connection_pool (2.2.3)
diff-lcs (1.3)
i18n (1.8.5)
i18n (1.8.7)
concurrent-ruby (~> 1.0)
method_source (1.0.0)
minitest (5.14.1)
minitest (5.14.3)
oj (3.10.14)
parallel (1.19.2)
parser (2.7.1.4)
Expand Down Expand Up @@ -67,11 +67,10 @@ GEM
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
thread_safe (0.3.6)
tzinfo (1.2.7)
thread_safe (~> 0.1)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (1.7.0)
zeitwerk (2.4.0)
zeitwerk (2.4.2)

PLATFORMS
ruby
Expand Down
5 changes: 4 additions & 1 deletion examples/order_placed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

module Examples
class OrderPlaced < EventRouter::Event
event_options queue: :orders, retry: false

deliver_to :notifications,
handler: Examples::Notifications
handler: Examples::Notifications,
queue: :notifications

deliver_to :event_store,
handler: Examples::EventStore::OrderPlaced,
Expand Down
2 changes: 2 additions & 0 deletions examples/sidekiq/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
:concurrency: 1
:queues:
- [event_router, 1]
- [notifications, 2]
- [orders, 2]
22 changes: 0 additions & 22 deletions lib/event_router/delivery_adapters/helpers/deliver.rb

This file was deleted.

6 changes: 4 additions & 2 deletions lib/event_router/delivery_adapters/helpers/sidekiq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ module Helpers
module Sidekiq
module_function

extend EventRouter::Helpers::Event

def process_event(event, serialized_event: nil)
serialized_event ||= EventRouter.serialize(event)

options = EventRouter::DeliveryAdapters::Sidekiq.options
yield_destinations(event) do |destination, serialized_payload|
options = destination_options(destination, EventRouter::DeliveryAdapters::Sidekiq)

Helpers::Deliver.yield_destinations(event) do |destination, serialized_payload|
Workers::SidekiqDestinationDeliveryWorker
.set(queue: options[:queue], retry: options[:retry])
.perform_async(destination.name, serialized_event, serialized_payload)
Expand Down
8 changes: 4 additions & 4 deletions lib/event_router/delivery_adapters/sidekiq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

require 'sidekiq'

require_relative '../serializer'
require 'event_router/serializer'
require 'event_router/helpers/event'

require_relative 'helpers/deliver'
require_relative 'helpers/sidekiq'

require_relative 'workers/sidekiq_destination_delivery_worker'
require_relative 'workers/sidekiq_event_delivery_worker'

Expand All @@ -29,7 +28,8 @@ def deliver(event)
end

def deliver_async(event)
serialized_event = EventRouter.serialize(event)
serialized_event = EventRouter.serialize(event)
options = EventRouter::Helpers::Event.event_options(event, self)

Workers::SidekiqEventDeliveryWorker
.set(queue: options[:queue], retry: options[:retry])
Expand Down
10 changes: 6 additions & 4 deletions lib/event_router/destination.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module EventRouter
class Destination
# Attributes
attr_reader :name, :handler, :handler_method,
:prefetch_payload, :payload_method
:prefetch_payload, :payload_method,
:options

# Constants
DEFAULT_ATTRIBUTES = {
Expand All @@ -22,9 +23,10 @@ def initialize(name, handler:, **opts)

@name = name
@handler = handler
@handler_method = opts[:handler_method]
@prefetch_payload = opts[:prefetch_payload]
@payload_method = opts[:payload_method] || "#{name}_payload"
@handler_method = opts.delete(:handler_method)
@prefetch_payload = opts.delete(:prefetch_payload)
@payload_method = opts.delete(:payload_method) || "#{name}_payload"
@options = opts
end

def process(event, payload)
Expand Down
5 changes: 5 additions & 0 deletions lib/event_router/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Event
attr_accessor :correlation_id

class_attribute :destinations, default: {}, instance_writer: false
class_attribute :options, instance_writer: false

def initialize(uid: SecureRandom.uuid, correlation_id: SecureRandom.uuid, created_at: Time.now, **payload)
@uid = uid
Expand Down Expand Up @@ -45,6 +46,10 @@ def deliver_to(name, opts = {})
destinations[name] = EventRouter::Destination.new(name, **opts)
end

def event_options(opts)
self.options = opts
end

def publish(**attrs)
EventRouter.publish(new(**attrs))
end
Expand Down
30 changes: 30 additions & 0 deletions lib/event_router/helpers/event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module EventRouter
module Helpers
module Event
module_function

def yield_destinations(event)
event.destinations.each do |_name, destination|
if destination.prefetch_payload?
payload = destination.extra_payload(event)
serialized_payload = EventRouter.serialize(payload)
end

yield destination, serialized_payload if block_given?
end
end

def event_options(event, adapter)
return adapter.options unless event.options?

adapter.options.merge(event.options)
end

def destination_options(destination, adapter)
adapter.options.merge(destination.options)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/event_router/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module EventRouter
VERSION = '0.2.0'
VERSION = '0.3.0'
end
74 changes: 74 additions & 0 deletions spec/event_router/helpers/event_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require 'event_router/helpers/event'

RSpec.describe EventRouter::Helpers::Event do
describe '.yield_destinations' do
subject { described_class.yield_destinations(event) }

let(:event) { DummyEvent.new }

let(:expected_args) do
event.destinations.map { |_, destination| [destination, anything] }
end

it 'yields the event destinations with serialized payload' do
expect { |b| described_class.yield_destinations(event, &b) }.to yield_successive_args(*expected_args)
end

it 'serializes the payload' do
expect(EventRouter).to receive(:serialize).once

subject
end
end

describe '.event_options' do
subject { described_class.event_options(event, adapter) }

let(:event) { DummyEvent.new }
let(:adapter) { DummyDeliveryAdapter }
let(:adapter_options) { { option_1: :adapter, option_2: :adapter } }

before { allow(adapter).to receive(:options) { adapter_options } }

context 'when event has custom options' do
let(:event_options) { { option_1: :event } }

before { allow(event).to receive(:options) { event_options } }

it 'merges the event options to the adapter options' do
is_expected.to eq(option_1: :event, option_2: :adapter)
end
end

context 'when event does not have any custom options' do
it 'returns the adapter options' do
is_expected.to eq(adapter_options)
end
end
end

describe '.destination_options' do
subject { described_class.destination_options(destination, adapter) }

let(:adapter) { DummyDeliveryAdapter }
let(:adapter_options) { { option_1: :adapter, option_2: :adapter } }

before { allow(adapter).to receive(:options) { adapter_options } }

context 'when destination has custom options' do
let(:destination) { EventRouter::Destination.new(:notifications, handler: :any, option_1: :destination) }

it 'merges the destination options to the adapter options' do
is_expected.to eq(option_1: :destination, option_2: :adapter)
end
end

context 'when destination does not have any custom options' do
let(:destination) { EventRouter::Destination.new(:notifications, handler: :any) }

it 'returns the adapter options' do
is_expected.to eq(adapter_options)
end
end
end
end

0 comments on commit 742b8d5

Please sign in to comment.