Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggested configuration defaults #153

Open
pawelpacana opened this issue Oct 26, 2017 · 8 comments

Comments

5 participants
@pawelpacana
Copy link
Member

commented Oct 26, 2017

I have a feeling there are several configuration snippets floating around which don't necessarily blend well with each other.

I consider RailsEventStore as an ecosystem of several gems which includes (and is not limited to) aggregate_root and command_bus. There's a Rails middleware addition for RailsEventStore itself and soon there will be web stream browser.

How about changing suggested defaults to following structure;

Rails.application.configure do
  config.x.rails_event_store.client           = RailsEventStore::Client.new
  config.x.rails_event_store.request_metadata = ->(env) { { kaka: 'dudu' } }
  config.x.rails_event_store.command_bus      = Arkency::CommandBus.new
end

Other related gems could then rely on such defaults, i.e. AggregateRoot.configuration.default_event_store.

Thoughts?

Reference: http://guides.rubyonrails.org/v5.1/configuring.html#custom-configuration

@fidel

This comment has been minimized.

Copy link
Contributor

commented Oct 27, 2017

👍🏻

@paneq

This comment has been minimized.

Copy link
Member

commented Oct 27, 2017

Definitely something worth improvement.

Also I don't like how differently they are configured:

# global
AggregateRoot.configure do |config|
  config.default_event_store = RailsEventStore::Client.new
end

# instance with arguments
event_store = RailsEventStore::Client.new(
  event_broker: RailsEventStore::EventBroker.new(
    dispatcher: RailsEventStore::ActiveJobDispatcher.new(
      proxy_strategy: RailsEventStore::AsyncProxyStrategy::AfterCommit.new
    )
  )
)

# rails config
config.to_prepare do
  config.command_bus = Arkency::CommandBus.new
  register = command_bus.method(:register)

  { FooCommand => FooService.new(event_store: event_store).method(:foo),
    BarCommand => BarService.new,
  }.map(&:register)
end

etc etc

@paneq

This comment has been minimized.

Copy link
Member

commented Oct 27, 2017

Also in RES code itself (another global):

RailsEventStore.event_repository = RailsEventStoreActiveRecord::EventRepository.new
@paneq

This comment has been minimized.

Copy link
Member

commented Nov 25, 2017

I just found out about RailsEventStore.event_repository again and I am like 🙀

@paneq

This comment has been minimized.

Copy link
Member

commented Nov 25, 2017

@pawelpacana pawelpacana referenced this issue Jan 27, 2018

Closed

Release 1.0 #185

@andrzejsliwa

This comment has been minimized.

Copy link
Member

commented Feb 7, 2018

@pawelpacana i'm using such configuration

in config/application.rb

    config.to_prepare do
      Rails.configuration.core = CoreConfiguration.new
    end

in app/domains/core_configuration.rb

require "aggregate_root"

class CoreConfiguration
  EVENTS_CLASS_REMAPPING = {
    # Example mapping in case of refactoring (move or rename)
    # "SomeDomain::Events::SomeEvent" => "SomeDomain::Events::SomeCreatedEvent"
  }.freeze

  def initialize(
    repository: Infra::EventRepository
      .new(mapper: RubyEventStore::Mappers::Default.new(events_class_remapping: EVENTS_CLASS_REMAPPING)),
    event_store: RailsEventStore::Client.new(repository: repository),
    command_bus: Infra::CommandBus.new,
    command_injector: Infra::CommandInjector.new(command_bus: command_bus)
  )
    @event_store      = event_store
    @command_bus      = command_bus
    @command_injector = command_injector

    configure_aggregate_root(event_store)
    setup_event_handler_strategy
    setup_read_models(event_store)
    register_event_handlers(event_store)
    register_command_handlers(command_bus)
  end

  def configure_aggregate_root(event_store)
    AggregateRoot.configure do |config|
      config.default_event_store = event_store
    end
  end

  def setup_event_handler_strategy
    Rails.configuration.event_handler_strategy =
      %w[development test].include?(Rails.env) ? :throw : :notify
  end

  def register_event_handlers(event_store)
    @all_event_handlers = AllEventHandlers.new
    @all_event_handlers.register(event_store: event_store)
  end

  def register_command_handlers(command_bus)
    @all_command_handlers = AllCommandHandlers.new
    @all_command_handlers.register(command_bus: command_bus)
  end

  def setup_read_models(event_store)
    @all_read_models = AllReadModels.new
    @all_read_models.register(event_store: event_store)
  end

  attr_reader :event_store,
              :command_bus,
              :all_command_handlers,
              :all_read_models,
              :all_event_handlers,
              :command_injector
end

everywhere when I need deps related to my reloadable core configuration:

    def register(event_store: Rails.configuration.core.event_store)

It's providing my own configuration object. Important part of it is handling reloading (reload! in rails console),
by replacing instances to avoid multiple registrations of handlers. I like having freedom
about this configuration. I'm worried if to strong convention will block possible usages.

If you are going to direction of providing nice default, then handling of reload on command/event handlers is pretty high on my priority list.

@paneq

This comment has been minimized.

Copy link
Member

commented Mar 12, 2018

Idea: container-based dependency injection? Using something like React-context which i passed down to everything. Basically all dependencies would be provided on top-level and objects from the middle/down of components tree could look up its depedencies in such configuration.

Perhaps this is no different from @pawelpacana proposal

Rails.application.configure do
  config.x.rails_event_store.client           = RailsEventStore::Client.new
  config.x.rails_event_store.request_metadata = ->(env) { { kaka: 'dudu' } }
  config.x.rails_event_store.command_bus      = Arkency::CommandBus.new
end

and config.x.rails_event_store is such store but I was thinking more about per-instance than per global.

@paneq

This comment has been minimized.

Copy link
Member

commented Mar 12, 2018

RailsEventStore::Client.new(config: {
  repository: ...,
  mapper: ...,
  event_bus: ..,
})

etc

paneq added a commit that referenced this issue Mar 17, 2018

Remove global
No idea why it was introduced at all.

Issue: #153

@mpraglowski mpraglowski added this to the 1.0.0 milestone Jul 31, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.