- Fix Sequent CLI
- Sequent now requires at least Ruby 3.2, ActiveRecord 7.1, and PostgreSQL 14.
- The internal database schema has been re-organized to support table
partitioning so the events of related aggregates can be stored
together. Partitioning is optional. You can override the
AggregateRoot#events_partition_key
method to return the partition key of an aggregate that will be used by PostgreSQL to store the events in the correct partition. - Storage logic of Sequent is now done by PostgreSQL stored procedures. This reduces the number of round-trips necessary between the Ruby process and the PostgreSQL server and optimizes storage requirements.
AggregateRoot#take_snapshot!
has been replaced withAggregateRoot#take_snapshot
which returns the snapshot instead of adding it to the uncommitted events. Snapshots can be stored usingEventStore#store_snapshots
method.- The
stream_records
,event_records
, andcommand_records
relations are no longer tables but views on the underlyingaggregates
,events
, andcommands
tables. These views take care of joining related tables using the correct partitioning key and type ids. The views are mainly for backwards compatibility with the*Record
Ruby classes and can only be used for querying. For updates theEventStore
(and higher-levelAggregateRepository
) classes should be used. New APIs have been added so there is no longer a need to use ActiveRecord methods directly to manage the event store. - Events, commands, and snapshot are now serialized directly to a
JSON
orJSONB
column. TheTEXT
column type is no longer supported. JSON size is minimized by extracting various repetitive fields (such asaggregate_id
) into database columns. - Snapshots are now stored into a separate
snapshot_records
table instead of being mixed in with events in theevents
table. This also makes it possible to store snapshots without an associated command record. Aggregates that need snapshots are tracked in a separateaggregates_that_need_snapshots
so that snapshots can be created more quickly by a background snapshotting process. - The
parent
,origin
andchildren
methods ofCommandRecord
andEventRecord
have been replaced by more specific methods (origin_command
,parent_event
, etc) and will always return a record of the appropriate type. - Events that are updated or deleted (a rare occurrence) are archived
into the
saved_event_records
table. - The
id
column ofaggregates
has been removed and the primary key is now theaggregate_id
column. - The
id
column ofevents
has been removed and the primary key are now theaggregate_id
andsequence_number
columns.
- Many documentation improvements.
- Other small bug fixes.
Small bugfix for metadata tables migrations. See #418. Thanks evsasse.
BREAKING CHANGE:
- Replaying all events for the view schema (using
sequent:migrate:online
andsequent:migrate:offline
) now make use of the PostgreSQL committed transaction id (xact_id()
) to track events that have already been replayed. The replayed ids table (specified by the removedSequent::configuration.replayed_ids_table_name
option) is no longer used and can be dropped from your database. There is no activerecord migration provided for the event store to add thexact_id
since depending on the size of the event store you may want to take run this migration yourself. ReplaceSCHEMA_NAME
with the name of the sequent schema:
BEGIN;
ALTER TABLE SCHEMA_NAME.event_records ADD COLUMN xact_id bigint;
COMMIT;
BEGIN;
# SET max_parallel_maintenance_workers = 8; # optionally set this depending on size of your event_records
# ALTER TABLE SCHEMA_NAME.event_records SET (parallel_workers = 8); # optionally set this depending on size of your event_records
CREATE INDEX event_records_xact_id_idx ON SCHEMA_NAME.event_records (xact_id) WHERE xact_id IS NOT NULL;
# ALTER TABLE SCHEMA_NAME.event_records RESET (parallel_workers); # optionally set this depending on size of your event_records
COMMIT;
ALTER TABLE SCHEMA_NAME.event_records ALTER COLUMN xact_id SET DEFAULT pg_current_xact_id()::text::bigint;
Next to this migration make sure you copy over the new sequent_schema.rb
into your project so when you regenerate the database from scratch
in for instance your development environment you have the correct version.
Other notable changes:
- The
MessageDispatcher
class has been removed. - Instance-of routes in projectors and other message handlers now use an optimized lookup mechanism. These are the most common handlers (
on MyEvent do ... end
). - Many optimizations were applied to the
ReplayOptimizedPostgresPersistor
:- Multi-value indexes are no longer supported, each column is now individually indexed. When a where clauses references multiple indexed columns all applicable indexes are used. For backwards compatibility multi-column index definitions are automatically changed to single-column indexes (one for each colum in the multi-column definition).
- Default indexed columns can be specified when instantiating the
ReplayOptimizedPostgresPersistor
. - Indexed values are now automatically frozen.
- Array matching and string/symbol matching in where-clauses now work for indexed columns as well.
- The internal struct classes are now generated differently and these classes are no longer associated with a Ruby constant so cannot be referenced from your code.
- Added possibility
enable_autoregistration
for automatically registering all Command and EventHandlers - In a Rails app all code will be eager loaded when
enable_autoregistration
is set to true upon sequent initialization viaRails.autoloaders.main.eager_load(force: true)
. If other parts of your app (esp initializers) are dependent on code not being loaded yet you can ensure Sequent loads as last by renaming the initializer to e.g.zz_sequent.rb
as Rails loads initializers in alphabetical order.
BREAKING CHANGES:
- Introduced
event_store_cache_event_types
as alternative for manually instantiating the EventStore yourself if you want to disable caching of event types. - Calling
Sequent.configure
twice will now create a new instance of the configuration instead of changing the current instance. This is done to better support Rails apps and the reload functionality during development.
- Drop support for ruby < 3
- Upgraded ActiveStar
- Add support for ruby 3.2
- Changed the default type of
aggregate_id
insequent_schema
touuid
since Postgres support this for quite long. - Added support for applications using ActiveRecord multiple database connections feature
- Improved out-of-the-box Rails support by fixing various bugs and providing Rake task to ease integration. See for more details: https://www.sequent.io/docs/rails-sequent.html
- Introduce
SEQUENT_ENV
instead ofRACK_ENV
.SEQUENT_ENV
defaults to the value ofRAILS_ENV
orRACK_ENV
. - Introduce
Sequent.configuration.time_precision
which defaults toActiveSupport::JSON::Encoding.time_precision
which is the precision "after seconds" to store time in json format when an event is serialized. - Custom command validations will now be translated according to the locale set by
Sequent.configuration.error_locale_resolver
BREAKING CHANGES:
- Since
DateTime
is deprecated in the Ruby std lib the standard attributecreated_at
ofEvent
andCommand
is now aTime
. This should not be a problem when serializing an deserializing but might be breaking if you rely on the fact it being aDateTime
rather than aTime
. - Renamed file of
Sequent::Test::WorkflowHelpers
toworkflow_helpers
. If you require this file manually you will need to update it's references - You now must "tag" specs using
Sequent::Test::WorkflowHelpers
with the following metadataworkflows: true
to avoid collision with other specs - Bugfix:
rake sequent:migrate:online
will now callreset_column_information
when done. Otherwise a subsequentsequent:migrate:offline
called in the same memory space fails.
- Introduce several advanced features for
Sequent::Core::Helpers::MessageHandler
s (ie.Sequent::AggregateRoot
,Sequent::Projector
,Sequent::Workflow
andSequent::CommandHandler
), namely:- Message matching (see https://www.sequent.io/docs/concepts/advanced.html#message-matching)
- Load time options (see https://www.sequent.io/docs/concepts/advanced.html#message-handler-load-time-options)
on MyEvent, MyEvent
will now raise an error stating the duplicate argumentson
without arguments will now raise an error- Declaring duplicate
attrs
will now raise an error
- Add ability to to load aggregates up until a certain point in time (use with caution)
- Support for ActiveStar 7.x
- Support for Ruby 3.1
- Various documentation fixes
- Upgrade to latest ar 6.1.4.x version
- Various setup fixes when doing
sequent new myapp
- Improve
dry_run
feature by using real event store
- Improve performance when running specs by not using
descendants
- Support for ActiveRecord 6.1.x
- Fixed some rake tasks for snapshotting (Thanks HEROGWP)
- Improve
ReplayOptimizedPostgresPersistor::Index
- Various improvements to the database config (to use database url and aliases) (Thanks Bér Kessels)
- Allow for event upcasting
- Add rubocop
- Changed default ruby to 3.0.0 release
- Added
database_schema_directory
configuration parameter to determine where to findsequent_schema.rb
andsequent_migrations.rb
. Currently it has the same default asdatabase_config_directory
- Dropped support for ruby < 2.7
- Moved to Github Actions for CI
- Allow splitting of indices and table definition in sql files to speed up replaying projectors
- Changed default ruby to latest 2.6 release
- Added support for ActiveRecord 6.0
- Added documentation for using with Rails
- Added alter table capabilities to migrations. Useful for larger projections.
- Added
Sequent::Projector.manages_no_tables
.
- Introduced
strict_check_attributes_on_apply_events
. Sequent will fail when callingapply
with unknown attributes.
Introduces optional event_aggregate_id
and event_sequence_number
columns to the command_records
table.
This enables keeping track of events causing commands in workflows.
To add these columns to an existing event store you can use this sql to add them:
Please note these sql statements use the uuid
type for aggregate_id
.
ALTER TABLE command_records ADD COLUMN event_aggregate_id uuid;
ALTER TABLE command_records ADD COLUMN event_sequence_number integer;
CREATE INDEX CONCURRENTLY index_command_records_on_event ON command_records(event_aggregate_id, event_sequence_number);
The most notable changes are:
- Added more documentation on https://www.sequent.io
- Added support for AR 5.2
- Added rake task to support installation on existing databases
The most notable changes are:
- Added extensive documentation for Sequent.
- Addition of more sophisticated way of replaying. See the documentation on how to configure.
- Dropped support for AR < 5.0
- Deprecated MigrateEvents as strategy for event migration
- Renamed Sequent::Core::BaseEventHandler to Sequent::Core::Projector
- Renamed Sequent::Core::Sessions::ActiveRecordSession to Sequent::Core::Persistors::ActiveRecordPersistor
- Renamed Sequent::Core::Sessions::ReplayEventsSession to Sequent::Core::Persistors::ReplayOptimzedPostgresPersistor
The most notable changes are:
To illustrate the difference see example below:
# command c1 results in event e1
on c1 do
apply e1
end
# workflow: event e1 results in new command c3
on e1 do
execute_commands(c3)
end
# main
execute_commands(c1, c2)
Prior to version 1.1 the order is as follows:
c1
c3
c2
e1
As you can see command c3
is executed before c2
although c2
was scheduled before c3
.
As of version 1.1 the order will be:
c1
c2
c3
e1
Commands and events are added to the queues as they occur and than handled in that order. If you have never had workflows scheduling new commands in the foreground nothing changes. If you have used workflows in the foreground the order will be different, so ensure your system still behaves correctly.
The Sequent::Core::EventStore::PublishEventError
is renamed to Sequent::Core::EventPublisher::PublishEventError
Another possible breaking change is the way the config is setup. The sequent config now global, so some sequent classes in the config do not take parameters anymore. You will need to change your sequent config, and will have affect on your tests. Please see the docs and the example apps for more information.
Full list of changes:
- New: Adding
TakeSnapshot
command to enable fine-grained support for snapshotting aggregates #92 - Improvement: Minimize differences between test environment and normal environment #93
- Bugfix: Fix query to load multiple aggregates of which one is snapshotted #94
- Improvement: Speed up event query #95
- New: Added
create_records
method available toBaseEventHandlers
to insert multiple records in one go #96 #100 - New: Added queue-based command and event publishing to ensure commands and events are handled in order they occurred #97
- Improvement: Update
oj
to mimic ActiveSupport version 5. Thanks @respire! #98 - Bugfixes: Fix sequent for AR => 5 #99
- Improvement: Global sequent config #101