lib/aggro/aggregate.rb in aggro-0.0.3 vs lib/aggro/aggregate.rb in aggro-0.0.4

- old
+ new

@@ -1,20 +1,19 @@ module Aggro # Public: Mixin to turn a PORO into an Aggro aggregate. module Aggregate extend ActiveSupport::Concern include EventDSL + include Logging def initialize(id) @id = id - @projections = self.class.projections.reduce({}) do |h, (name, klass)| - class_eval { define_method(name) { @projections[name] } } - h.merge name => klass.new(id) - end + start_projections + restore_from_event_stream - Aggro.event_bus.subscribe(id, self) + log INFO, 'Restored to memory' end private def apply_command(command) @@ -22,42 +21,70 @@ @_context = command.attributes handler = self.class.handler_for_command(command.class) instance_exec command, &handler + rescue => e + log ERROR, "Couldn't apply command\n#{e}\n#{e.backtrace.join "\n"}" + + raise e ensure @_context = nil end def did fail 'Must be called within a command handler' unless @_context @event_caller ||= EventProxy.new(self, @id) end + def log(level, message, &block) + super level, "#{self.class}/#{@id}", message, &block + end + + def restore_from_event_stream + Aggro.event_bus.subscribe(@id, self) + rescue => e + log FATAL, "Couldn't restore from events\n#{e}\n#{e.backtrace.join "\n"}" + end + def run_query(query) return unless self.class.responds_to? query handler = self.class.handler_for_query(query.class) instance_exec query, &handler - rescue RuntimeError => e + rescue => e + log ERROR, "Couldn't complete query\n#{e}\n#{e.backtrace.join "\n"}" QueryError.new(e) end + def start_projections + @projections = self.class.projections.reduce({}) do |h, (name, klass)| + class_eval { define_method(name) { @projections[name] } } + h.merge name => klass.new(@id) + end + rescue => e + log FATAL, "Couldn't start projections\n#{e}\n#{e.backtrace.join "\n"}" + end + class_methods do def allows(command_class, &block) command_handlers[command_class] = block if block end def allows?(command) command_handlers.keys.include? command.class end def create(id = SecureRandom.uuid) + fail ArgumentError unless id && id.length == 36 + find(id).create end def find(id) + fail ArgumentError unless id && id.length == 36 + AggregateRef.new id, name end def handler_for_command(command_class) command_handlers[command_class]