Skip to content

Commit

Permalink
feat: add sync and sidekiq delivery adapters (#7)
Browse files Browse the repository at this point in the history
* feat: add memory and sidekiq delivery adapters
  • Loading branch information
ahmad-elassuty authored Jan 19, 2021
1 parent 156364e commit 85ae18d
Show file tree
Hide file tree
Showing 46 changed files with 847 additions and 218 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/specs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu, macos]
ruby: [2.5, 2.6, 2.7, head]
ruby: [2.5, 2.6, 2.7]

steps:
- uses: actions/checkout@v2
Expand Down
9 changes: 3 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ PATH
remote: .
specs:
event_router (0.1.0)
activejob
activesupport

GEM
remote: https://rubygems.org/
specs:
activejob (6.0.3.2)
activesupport (= 6.0.3.2)
globalid (>= 0.3.6)
activesupport (6.0.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
Expand All @@ -22,12 +19,11 @@ GEM
concurrent-ruby (1.1.7)
connection_pool (2.2.3)
diff-lcs (1.3)
globalid (0.4.2)
activesupport (>= 4.2.0)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
method_source (1.0.0)
minitest (5.14.1)
oj (3.10.14)
parallel (1.19.2)
parser (2.7.1.4)
ast (~> 2.4.1)
Expand Down Expand Up @@ -82,6 +78,7 @@ PLATFORMS

DEPENDENCIES
event_router!
oj
pry
pry-byebug
rspec (~> 3.0)
Expand Down
5 changes: 1 addition & 4 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,5 @@ require 'event_router'
# with your gem easier. You can also use a different console, if you like.

# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start

require 'pry'
Pry.start(__FILE__)
Pry.start
3 changes: 2 additions & 1 deletion event_router.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

# Dependencies
spec.add_dependency 'activejob'
spec.add_dependency 'activesupport'

# Development dependencies
spec.add_development_dependency 'oj'
spec.add_development_dependency 'pry'
spec.add_development_dependency 'pry-byebug'
spec.add_development_dependency 'rspec', '~> 3.0'
Expand Down
6 changes: 6 additions & 0 deletions examples/common.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

require_relative 'event_store/order_placed'
require_relative 'notifications'
require_relative 'payment_received'
require_relative 'order_placed'
15 changes: 15 additions & 0 deletions examples/event_store/order_placed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Examples
module EventStore
class OrderPlaced
def self.handle(event:, payload:)
puts "#{'=' * 10} [EventStore] #{'=' * 10}"
puts 'Received order_placed'
puts event.inspect
puts payload.inspect
puts '=' * 32
end
end
end
end
22 changes: 22 additions & 0 deletions examples/notifications.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Examples
module Notifications
module_function

def order_placed(event:, payload:)
puts "#{'=' * 10} [Notifications] #{'=' * 10}"
puts 'Received order_placed'
puts event.inspect
puts payload.inspect
puts '=' * 35
end

def payment_received(event:, **_payload)
puts "#{'=' * 10} [Notifications] #{'=' * 10}"
puts 'Received payment_received'
puts event.inspect
puts '=' * 35
end
end
end
21 changes: 21 additions & 0 deletions examples/order_placed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module Examples
class OrderPlaced < EventRouter::Event
deliver_to :notifications,
handler: Examples::Notifications

deliver_to :event_store,
handler: Examples::EventStore::OrderPlaced,
handler_method: :handle,
prefetch_payload: true,
payload_method: :store_payload

# Extra payload
def store_payload
{
id: SecureRandom.uuid
}
end
end
end
8 changes: 8 additions & 0 deletions examples/payment_received.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

module Examples
class PaymentReceived < EventRouter::Event
deliver_to :notifications,
handler: Examples::Notifications
end
end
2 changes: 1 addition & 1 deletion sidekiq.yml → examples/sidekiq/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
:concurrency: 1
:queues:
- [default, 1]
- [event_router, 1]
15 changes: 15 additions & 0 deletions examples/sidekiq/run_console.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require 'bundler/setup'
require 'event_router'
require 'pry'

require_relative '../common'

EventRouter.configure do |config|
config.register_delivery_adapter :sidekiq, queue: :event_router, retry: 5

config.delivery_adapter = :sidekiq
end

Pry.start
11 changes: 11 additions & 0 deletions examples/sidekiq/run_server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require 'event_router'

require_relative '../common'

EventRouter.configure do |config|
config.register_delivery_adapter :sidekiq, queue: :event_router, retry: 5

config.delivery_adapter = :sidekiq
end
13 changes: 13 additions & 0 deletions examples/sync/run_console.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require 'bundler/setup'
require 'event_router'

require_relative '../common'

EventRouter.configure do |config|
config.delivery_adapter = :sync
end

require 'pry'
Pry.start
37 changes: 14 additions & 23 deletions lib/event_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,29 @@

require 'event_router/version'
require 'event_router/error'
require 'active_job'
require 'event_router/configuration'
require 'event_router/destination'
require 'event_router/event'
require 'event_router/event_serializer'
require 'event_router/deliver_event_job'

require 'examples/notifications'
require 'examples/event_store/order_placed'
require 'examples/order_placed'
require 'examples/payment_received'

require 'pry'
require 'event_router/event'
require 'event_router/delivery_adapters/base'
require 'event_router/serializers/base'
require 'event_router/publisher'
require 'event_router/serializer'
require 'event_router/configuration'

module EventRouter
module_function

def publish(*events)
correlation_id = events.first.correlation_id

events.each do |event|
event.correlation_id = correlation_id
def publish(events, adapter: EventRouter.configuration.delivery_adapter)
EventRouter::Publisher.publish(events, adapter: adapter)
end

event.destinations.each do |name, destination|
payload = destination.prefetch_payload? ? destination.payload_for(event) : nil
def serialize(event, adapter: EventRouter.configuration.serializer_adapter)
EventRouter::Serializer.serialize(event, adapter: adapter)
end

DeliverEventJob.perform_later(name, event, payload)
end
end
def deserialize(payload, adapter: EventRouter.configuration.serializer_adapter)
EventRouter::Serializer.deserialize(payload, adapter: adapter)
end

# Configurations
def configuration
@configuration ||= Configuration.new
end
Expand Down
68 changes: 44 additions & 24 deletions lib/event_router/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,67 @@

module EventRouter
class Configuration
attr_reader :delivery_adapter, :delivery_strategy
attr_reader :delivery_adapter, :delivery_adapters,
:serializer_adapter, :serializer_adapters

# Constants
DELIVERY_ADAPTERS = %i[
memory
].freeze

DELIVERY_STRATEGIES = %i[
async
sync
].freeze
def initialize
@delivery_adapters = {}
@serializer_adapters = {}

DEFAULT_CONFIGURATIONS = {
delivery_adapter: :memory,
delivery_strategy: :async
}.freeze
register_delivery_adapter(:sync)
@delivery_adapter = :sync

def initialize
@delivery_adapter = DEFAULT_CONFIGURATIONS[:delivery_adapter]
@delivery_strategy = DEFAULT_CONFIGURATIONS[:delivery_strategy]
register_serializer_adapter(:json)
@serializer_adapter = :json
end

def delivery_adapter=(adapter)
validate_inclusion(:delivery_adapter, adapter, DELIVERY_ADAPTERS)
def delivery_adapter=(adapter, _opts = {})
validate_inclusion!(:delivery_adapter, adapter, @delivery_adapters)

@delivery_adapter = adapter
end

def delivery_strategy=(strategy)
validate_inclusion(:delivery_strategy, strategy, DELIVERY_STRATEGIES)
def delivery_adapter_class(adapter)
@delivery_adapters[adapter]
end

def register_delivery_adapter(adapter, opts = {})
adapter_class = load_adapter_class(Publisher::ADAPTERS, adapter) || opts[:adapter_class]

adapter_class.options = opts
@delivery_adapters[adapter] = adapter_class
end

def serializer_adapter=(adapter)
validate_inclusion!(:serializer_adapter, adapter, @serializer_adapters)

@delivery_strategy = strategy
@serializer_adapter = adapter
end

def serializer_adapter_class(adapter)
@serializer_adapters[adapter]
end

def register_serializer_adapter(adapter, opts = {})
adapter_class = load_adapter_class(Serializer::ADAPTERS, adapter) || opts[:adapter_class]

@serializer_adapters[adapter] = adapter_class
end

private

def validate_inclusion(config, option, supported_options)
def load_adapter_class(adapters, adapter)
return nil unless adapters.key?(adapter)

require_relative adapters[adapter][:path]
Kernel.const_get(adapters[adapter][:adapter_class])
end

def validate_inclusion!(config, option, supported_options)
return if supported_options.include?(option)

raise Errors::UnsupportedOptionError.new(
config: config, option: option, supported_options: supported_options
config: config, option: option, supported_options: supported_options.keys
)
end
end
Expand Down
18 changes: 0 additions & 18 deletions lib/event_router/deliver_event_job.rb

This file was deleted.

27 changes: 27 additions & 0 deletions lib/event_router/delivery_adapters/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require_relative '../errors/required_option_error'

module EventRouter
module DeliveryAdapters
class Base
class << self
attr_reader :options

def options=(options)
validate_options!(options)

@options = options
end

def validate_options!(_options)
true
end

def deliver(_event)
raise NotImplementedError, "deliver method is not implemented for #{name}"
end
end
end
end
end
Loading

0 comments on commit 85ae18d

Please sign in to comment.