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]