Class: Sequent::Core::CommandService

Inherits:
Object
  • Object
show all
Defined in:
lib/sequent/core/command_service.rb

Overview

Single point in the application where subclasses of Sequent::Core::BaseCommand are executed. This will initiate the entire flow of:

  • Validate command

  • Call correct Sequent::Core::BaseCommandHandler

  • CommandHandler decides which Sequent::Core::AggregateRoot (s) to call

  • Events are stored in the Sequent::Core::EventStore

  • Unit of Work is cleared

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(configuration = CommandServiceConfiguration.new) ⇒ CommandService

DefaultCommandServiceConfiguration Configuration class for the CommandService containing:

+event_store+ The Sequent::Core::EventStore
+command_handler_classes+ Array of BaseCommandHandler classes that need to handle commands
+transaction_provider+ How to do transaction management. Defaults to Sequent::Core::Transactions::NoTransactions
+filters+ List of filter that respond_to :execute(command). Can be useful to do extra checks (security and such).


53
54
55
56
57
58
59
# File 'lib/sequent/core/command_service.rb', line 53

def initialize(configuration = CommandServiceConfiguration.new)
  @event_store = configuration.event_store
  @repository = AggregateRepository.new(configuration.event_store)
  @filters = configuration.filters
  @transaction_provider = configuration.transaction_provider
  @command_handlers = configuration.command_handler_classes.map { |handler| handler.new(@repository) }
end

Class Attribute Details

.configurationObject

Returns the value of attribute configuration.



33
34
35
# File 'lib/sequent/core/command_service.rb', line 33

def configuration
  @configuration
end

.instanceObject

Returns the value of attribute instance.



33
34
35
# File 'lib/sequent/core/command_service.rb', line 33

def instance
  @instance
end

Class Method Details

.configure {|configuration| ... } ⇒ Object

Creates a new CommandService and overwrites all existing config. The new CommandService can be retrieved via the CommandService.instance method.

If you don’t want a singleton you can always instantiate it yourself using the CommandService.new.

Yields:



41
42
43
44
45
# File 'lib/sequent/core/command_service.rb', line 41

def self.configure
  self.configuration = CommandServiceConfiguration.new
  yield(configuration) if block_given?
  self.instance = CommandService.new(configuration)
end

Instance Method Details

#execute_commands(*commands) ⇒ Object

Executes the given commands in a single transactional block as implemented by the transaction_provider

For each command:

  • All filters are executed. Any exception raised will rollback the transaction and propagate up

  • If the command is valid all command_handlers that handles_message? is invoked

  • The repository commits the command and all uncommitted_events resulting from the command



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/sequent/core/command_service.rb', line 68

def execute_commands(*commands)
  begin
    @transaction_provider.transactional do
      commands.each do |command|
        @filters.each { |filter| filter.execute(command) }

        raise CommandNotValid.new(command) unless command.valid?
        parsed_command = command.parse_attrs_to_correct_types
        @command_handlers.select { |h| h.handles_message?(parsed_command) }.each { |h| h.handle_message parsed_command }
        @repository.commit(parsed_command)
      end
    end
  ensure
    @repository.clear
  end

end

#remove_event_handler(clazz) ⇒ Object



86
87
88
# File 'lib/sequent/core/command_service.rb', line 86

def remove_event_handler(clazz)
  @event_store.remove_event_handler(clazz)
end