EventSourcing
DISCLAIMER
This gem is under development. DO NOT USE IN PRODUCTION ENVIRONMENT!!!!
The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object, and that these event objects are themselves stored in the sequence they were applied for the same lifetime as the application state itself.
Martin Fowler , https://martinfowler.com/eaaDev/EventSourcing.html
This gem provides a simple way of adding event sourcing behaviour to your models class.
You could find this base classes:
- AggregateRoot
- Id
- History
- Event
- EventDispatcher
- EventSubscriber
- StoredEvent
- EventStore (Facade)
- RedisEventStore
Installation
Add this line to your application's Gemfile:
gem 'simple_event_sourcing'
And then execute:
$ bundle
Or install it yourself as:
$ gem install simple_event_sourcing
Usage
Firts of all, you must add "event sourcing" behaviour to your model including the AggregateRoot Base Module
class Employee
include SimpleEventSourcing::AggregateRoot::Base
private_class_method :new
attr_reader :name, :title, :salary
def salary=(new_salary)
apply_record_event SalaryHasChangedEvent , new_salary: new_salary
end
def self.create(name,title,salary)
employee = new
employee.apply_record_event NewEmployeeIsHiredEvent,name: name,title: title, salary: salary
employee
end
on NewEmployeeIsHiredEvent do |event|
@name = event.name
@title = event.title
@salary = event.salary
end
on SalaryHasChangedEvent do |event|
@salary = event.new_salary
end
end
It´s important to notice use of named constructor "create" in order to leave the constructor for building an aggregate from its events history.
You must create your own domain events
class SalaryHasChangedEvent < SimpleEventSourcing::Events::Event
attr_reader :new_salary
def initialize(args)
@new_salary = args[:new_salary]
super(args)
end
def serialize
super.merge("new_salary" => new_salary)
end
end
After that, we must provide a handle in the out model for all domain event. SimpleEventSourcing provides a DSL to handle the applied events. You must provide a handler for each event
on SalaryHasChangedEvent do |event|
@salary = event.new_salary
end
Now you could apply and record events.
apply_record_event SalaryHasChangedEvent , new_salary: new_salary
Once you persist the entity you must store and publish all recorded events.
class EmployeeRepository
def initialize(event_store)
@event_store = event_store
end
def save(employee)
employee.publish_events.each do |event|
@event_store.commit event
SimpleEventSourcing::Events::EventDispatcher.publish(event)
end
end
def findById(id)
history = @event_store.get_history id
return Employee.create_from_history history
end
end
This gem provides a Redis Event Store or if you want, you could create your own usign "EventStoreBase" interface.
You could see this example running in https://github.com/malotor/simple_event_sourcing_example
Happy coding!
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/event_sourcing. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the EventSourcing project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.