Skip to content

Instantly share code, notes, and snippets.

@mariuszkapcia
Last active January 28, 2019 18:01
Show Gist options
  • Save mariuszkapcia/ce1afab1cc51633e112f8574aa1905c7 to your computer and use it in GitHub Desktop.
Save mariuszkapcia/ce1afab1cc51633e112f8574aa1905c7 to your computer and use it in GitHub Desktop.
AggregateRoot pattern with extracted events and persistence. Loading and storing of an aggregate is done by DeveloperStore service.
def register(cmd)
ActiveRecord::Base.transaction do
with_developer(cmd.developer_uuid) do |developer|
developer.register
DeveloperRegistered.strict(data: {
developer_uuid: cmd.developer_uuid,
fullname: cmd.fullname,
email: cmd.email
})
end
end
end
def with_developer(developer_uuid)
Developer.new.tap do |developer|
developer_version = @developer_store.load(developer, developer_uuid)
event = yield developer
@developer_store.store(event, developer_uuid, developer_version)
end
end
class Developer
HasBeenAlreadyRegistered = Class.new(StandardError)
EmailAddressNotUniq = Class.new(StandardError)
def initialize
@state = nil
end
def register
raise HasBeenAlreadyRegistered if @state == :registered
@state = :registered
end
end
class DeveloperStore
def load(developer, developer_uuid)
current_version = 0
@event_store.read.stream(stream_name(developer_uuid)).forward.each do |event|
case event
when DeveloperRegistered
apply_developer_registered(developer, event)
end
current_version += 1
end
current_version
end
def store(event, developer_uuid, developer_version)
@event_store.publish(
event,
stream_name: stream_name(developer_uuid),
expected_version: developer_version
)
end
private
def initialize(event_store:)
@event_store = event_store
end
def stream_name(developer_uuid)
"Developer$#{developer_uuid}"
end
def apply_developer_registered(developer, event)
developer.register(event.data[:fullname], event.data[:email])
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment