module Aggro::Aggregate

Public: Mixin to turn a PORO into an Aggro aggregate.

Public Class Methods

new(id) click to toggle source
# File lib/aggro/aggregate.rb, line 8
def initialize(id)
  @id = id

  start_projections
  restore_from_event_stream

  log INFO, 'Restored to memory'
end

Private Instance Methods

allows(command_class, &block) click to toggle source
# File lib/aggro/aggregate.rb, line 70
def allows(command_class, &block)
  command_handlers[command_class] = block if block
end
allows?(command) click to toggle source
# File lib/aggro/aggregate.rb, line 74
def allows?(command)
  command_handlers.keys.include? command.class
end
apply_command(command) click to toggle source
# File lib/aggro/aggregate.rb, line 19
def apply_command(command)
  return unless self.class.allows? command

  @_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
command_handlers() click to toggle source
# File lib/aggro/aggregate.rb, line 116
def command_handlers
  Aggro.command_handlers[name]
end
create(id = SecureRandom.uuid) click to toggle source
# File lib/aggro/aggregate.rb, line 78
def create(id = SecureRandom.uuid)
  fail ArgumentError unless id && id.length == 36

  find(id).create
end
did() click to toggle source
# File lib/aggro/aggregate.rb, line 34
def did
  fail 'Must be called within a command handler' unless @_context

  @event_caller ||= EventProxy.new(self, @id)
end
find(id) click to toggle source
# File lib/aggro/aggregate.rb, line 84
def find(id)
  fail ArgumentError unless id && id.length == 36

  AggregateRef.new id, name
end
handler_for_command(command_class) click to toggle source
# File lib/aggro/aggregate.rb, line 90
def handler_for_command(command_class)
  command_handlers[command_class]
end
handler_for_query(query_class) click to toggle source
# File lib/aggro/aggregate.rb, line 94
def handler_for_query(query_class)
  query_handlers[query_class]
end
log(level, message, &block) click to toggle source
Calls superclass method Aggro::Logging#log
# File lib/aggro/aggregate.rb, line 40
def log(level, message, &block)
  super level, "#{self.class}/#{@id}", message, &block
end
projection(projection_name, via:) click to toggle source
# File lib/aggro/aggregate.rb, line 98
def projection(projection_name, via:)
  projections[projection_name] = via
end
projections() click to toggle source
# File lib/aggro/aggregate.rb, line 102
def projections
  @projections ||= {}
end
query_handlers() click to toggle source
# File lib/aggro/aggregate.rb, line 120
def query_handlers
  Aggro.query_handlers[name]
end
responds_to(query_class, &block) click to toggle source
# File lib/aggro/aggregate.rb, line 106
def responds_to(query_class, &block)
  query_handlers[query_class] = block if block
end
responds_to?(query) click to toggle source
# File lib/aggro/aggregate.rb, line 110
def responds_to?(query)
  query_handlers.keys.include? query.class
end
restore_from_event_stream() click to toggle source
# File lib/aggro/aggregate.rb, line 44
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
run_query(query) click to toggle source
# File lib/aggro/aggregate.rb, line 50
def run_query(query)
  return unless self.class.responds_to? query

  handler = self.class.handler_for_query(query.class)
  instance_exec query, &handler
rescue => e
  log ERROR, "Couldn't complete query\n#{e}\n#{e.backtrace.join "\n"}"
  QueryError.new(e)
end
start_projections() click to toggle source
# File lib/aggro/aggregate.rb, line 60
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