All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.17.1 - 2024-08-20
- updated sqlx to 0.8.0
0.17.0 - 2024-06-10
- [#196]:
AggregateManager::handle_command
now returns the updated aggregate state, instead of()
.
0.16.0 - 2024-05-08
Note: this version contains hard breaking changes in the AggregateManager
API - refer to #192 and #194.
- [#194]: New
LockedLoad
type to correctly manage locked loads inAggregateManager
.
- [#192]:
AggregateManager::handle_command
now returns a concreteResult<Result<(), Aggregate::Error>, Store::Error>
and is no longer generic in error. - [#194]:
AggregateManager::lock_and_load
now returns aLockedLoad
.
- [#194]: Previously, concurrent
lock_and_load
s would drop the lock if the aggregate was empty, leading to concurrent writes (caught by optimistic locking). This is now correctly handled via theLockedLoad
result.
0.15.0 - 2024-04-03
- [#187]: Make the
AggregateManager
deref
blanket implementation work for smart pointers. - [#191]: Add new generic on
PgStore
andSchema
trait to decouple persistence fromAggregate::Event
.
- [#191]: Updated MSRV to
1.74.0
. - [#191]: Renamed
Event
trait toPersistable
(this should not affect users of the library since users of the library benefit from a blanket implementation).
- [#189]: Fixed examples not compiling in Rust
1.75.0
.
- [#191]: Removed broken
sql
feature.
0.14.0 - 2024-01-09
- [#185]:
AggregateManager::handle_command
is generic in Error.
- [#185]:
PgStore
is now alwaysClone
able.
0.13.0 - 2023-09-12
- [#147]: Event upcasting, available under
upcasting
feature flag, disabled by default. - [#164]: Kafka messages are now published using the record key, set as the event
aggregate_id
. - [#175]: Connection manager for RabbitMQ event bus to handle connection outages and fail-overs.
0.12.0 - 2023-06-09
- [#148]:
ReplayableEventHandler
trait to mark anEventHandler
as replayable or not. This does not stick toTransactionalEventHandlers
since it is taken for granted that they must always be replayable. - [#149]:
PgStoreBuilder
struct, currently the sole method for constructing aPgStore
. - [#151]: The
EventBus
trait is integrated with thePgStore
implementation to facilitate the publishing of events after they have been processed by the handlers. - [#152]:
MigrationHandler
trait to run migrations while building a newPgStore
. - [#155]: Concrete implementations of the
EventBus
interface for Apache Kafka and RabbitMQ. These implementations are available under therabbit
andkafka
features. - [#155]: Docker compose file for local development and testing.
- [#156]: The
table_name
andadd_event_handler
functions toPgStore
. - [#156]: Generic
Rebuilder
trait and concretePgRebuilder
struct facilities to rebuild a single aggregate. These implementations are available under therebuilder
feature. - [#157]: The
TransactionalEventHandler
now includes a new generic type argument that allow to specify the error return type. - [#157]: The
EventStore
trait now takes theAggregate
as associated type and now includes a new associated type that allow to specify the error return type. - [#157]: New
PgStoreError
type as error return type forPgStore
.
- [#148]:
Projector
andPolicy
no longer exists. Replaced withEventHandler
andTransactionalEventHandler
. - [#150]:
AggregateManager
is no longer a trait; it now lives as a struct. - [#150]: The
EventStore
,PgStore
,EventHandler
,TransactionalEventHandler
andReplayableEventHandler
types, previously associated with theAggregateManager
trait, now have a simplified constraint that they are bound to theAggregate
trait. - [#153]: The
save_event
function in thePgStore
is now accessible only within the crate scope. - [#156]: The examples have been refactored as external executables and are no longer part of the cargo workspace.
- [#157]: The
AggregateManager
type bound has been changed fromAggregate
to anEventStore
type. - [#157]:
- [#157]: The return type error of the inner functions in
AggregateManager
has been modified fromAggregate::Error
to a new type calledAggregateManagerError<E>
. This change introduces a clear differentiation between anAggregate
error and anEventStore
error. - [#157]: The functions in the
EventStore
, including those in thePgStore
, now utilize the new error associated type as their return type. - [#161]: Moved some traits and structs in other packages
- The
esrs::AggregateManager
struct (previously a trait) moved intoesrs::manager
module. - The
esrs::postgres
module has been relocated and can now be found underesrs::store::postgres
. - The
esrs::EventStore
,esrs::EventStoreLockGuard
,esrs::StoreEvent
andesrs::UnlockOnDrop
objects moved toesrs::store
module.
- The
- [#153]:
PgStore
getters functionstransactional_event_handlers
,event_handlers
andevent_buses
. - [#153]:
PgStore
custompersist
function. - [#157]: The
Clone
,Send
, andSync
bounds on the associated types ofAggregate
have been eliminated. - [#161]: The
error
module has been removed and is no longer available.
0.11.0 - 2023-04-03
- [#144]
- projector
consistency
function has been renamed inpersistence
. - projector
Consistency
enum has been renamed inProjectorPersistence
. - projector
ProjectorPersistence
enum entries renamed inMandatory
andFallible
.
- projector
0.10.2 - 2023-02-16
- [#141]: log error in case of event projection or policy application failure
- [#141]: fixed tracing of event projection and policy application
0.10.1 - 2023-02-06
- [#136]:
select_all
query ordering was missing of sequence_number.
0.10.0 - 2022-11-30
- [#133]: atomic read/writes rework to avoid deadlocks in Policies.
Aggregate
:apply_events
has been removed, and its default implementation moved to a method ofAggregateState
.
AggregateManager
:lock_and_load
acquires a lock, then loads into memory the AggregateState preventing other atomic accesses. Dropping the AggregateState releases the resource.lock
has been removed in favour oflock_and_load
.handle_command
does not return the AggregateState anymore. This avoids race conditions where the returned state is already outdated, if another concurrent access has taken place at the same time.apply_events
has been removed, and its default implementation moved to a method ofAggregateState
.load
has been changed to return aResult<Option<_>, _>
, to explicit expose errors.
AggregateState
:- new
lock
field, which contains the exclusive access guard created whenlock_and_load
ing. All other fields are now private for better encapsulation. new
takes no argument, and generates a new state with a random UUID.with_id
generates a new state with the given UUID.apply_store_events
applies the given list of Events on self.set_lock
andtake_lock
methods to set and get the lock, to use when overriding the AggregateManager functionality.
- new
0.9.0 - 2022-11-21
- Added tracing spans for application of policies and projection of events
- [#129]: Atomic read/writes for aggregate states.
AggregateManager
:lock
method acquires a lock for the given aggregate state, preventing other atomic accesses. Dropping the lock releases the resource.
EventStore
:lock
trait function, required to return aEventStoreLockGuard
.
EventStoreLockGuard
, wrapping anUnlockOnDrop
trait object.UnlockOnDrop
marker trait, required for concrete types to be used asEventStoreLockGuard
.PgStore
:lock
implementation using Postgres' advisory locks.
PgStoreLockGuard
, holding the actual Postgres' lock and releasing it on drop.
- [#114]: Default
EventStore
implementation for everyBox<dyn EventStore<Manager = _>>
. This allows to define in theAggregateManager
theEventStore
associated type asBox<dyn EventStore<Manager = _>>
(withSend
+Sync
bounds). - [#115]: Added
apply_events
toAggregate
with default implementation. - [#122]:
Consistency
level enum.consistency
function toProjector
to instruct theEventStore
on the persistence guarantees with default implementation returningConsistency::Strong
.
- [#123]: Added
postgres
documentation in docs.rs withpackage.metadata.docs.rs
inCargo.toml
. Improved modules documentation.
- [#117]:
AggregateState::new
second parameter fromUuid
toimpl Into<Uuid>
.AggregateManager::load
first parameter fromUuid
toimpl Into<Uuid>
.AggregateState::delete
first parameter fromUuid
toimpl Into<Uuid>
.
- [#118]: Merged rebuild examples into one; removed mains and migrations from examples.
Note: this version contains hard breaking changes and may take a lot of time in order to upgrade library version! Refer to: #107, #108 and #109
-
AggregateManager
- should implement
name
function that act asIdentifier
. Be sure to not change the name previously set inIdentifier::name
function. This would cause the store to create a new table, losing pre-migration events. - depends on
Aggregate
, so user must implementAggregate
trait in order to implementAggregateManager
trait. - should implement
EventStore
associated type.
- should implement
-
EventStore::delete
function with which an entire aggregate could be deleted byaggregate_id
. -
PgStore
setup
function to create table and indexes if not exists. This function should be used only once at your application startup. It tries to create the event table and its indexes if they not exist.set_projectors
function to set the store projectors list.set_policies
function to set the store policies list.PgStore
and all its dependencies are now cloneable. Is behind and Arc and is safely cloneable.
-
Projector
should implementdelete
function.
-
Aliases of exposed traits and struct are hardly changed. Now most of internal objects are flatten in
esrs
module. -
Aggregate
- is now pure. API changed so user have to implement
Aggregate
for logic andAggregateManager
in order to handle persistence layer. handle_command
state argument changed from&AggregateState<Self::State>
to&Self::State
.apply_event
payload
parameter changed from reference to value (Self::Event
).
- is now pure. API changed so user have to implement
-
AggregateManager
- is now dependent by
Aggregate
and no default implementation is provided. To complete the migration for an aggregate handling the persistence layer is now mandatory for your type to implementAggregateManager
. - renamed function
handle
inhandle_command
. event_store
changed to return a reference to it's associated typeEventStore
.
- is now dependent by
-
EventStore
Event
andError
generics removed in favour ofManager: AggregateManager
associated type.
-
PgStore
new
function is now sync and its return value is no longer aResult
butSelf
. RemovedAggregate
type param.new
takes ownership of pool; removed projectors and policies params. Useset_projectors
orset_policies
instead to add them to the store.rebuild_events
renamed intostream_events
. Now it takes ansqlx::Executor
parameter.- policies behaviour is now that if one of them fails they fail silently. (override this behaviour with
Aggregate::store_events
usingEventStore::persist
function). Event
andError
trait generic params removed in favour ofManager: AggregateManager
.projectors
andpolicies
returns anArc
to value.
-
PgProjector
- renamed to
Projector
. - second param changed from
&mut PoolConnection<Postgres>
to&mut PgConnection
. Event
andError
trait generic params removed in favour ofManager: AggregateManager
.
- renamed to
-
PgPolicy
- renamed to
Policy
. Event
andError
trait generic params removed in favour ofManager: AggregateManager
.- moved to
esrs
root module. - removed second param (
&Pool<Postgres>
).
- renamed to
-
Policy::handle_event
does not havePool<Postgres
anymore as param. Executor should be put in the policy at instantiation time.
-
sqlite
feature and its implementation. -
Aggregate
validate_command
is removed; now validation should be made inhandle_command
.event_store
function is moved fromAggregate
toAggregateManager
.
-
EventStore
run_policies
. To customize the way policies behave overrideAggregate::store_events
usingEventStore::persist
function.close
function.
-
PgStore
test
function. Use#[sqlx::test]
in your tests to test the store.begin
,commit
androllback
functions.Event
generic type.Error
generic type.Projector
generic type.Policy
generic type.
-
Identifier
trait. -
Eraser
trait. -
PgProjectorEraser
trait. -
EraserStore
trait. -
ProjectorStore
trait. -
StoreEvent
bounds ofEvent
generic. -
AggregateState
new_with_state
removed due to potential inconsistency while loading state.
- Bump min version of supported Rust to 1.58 since <1.58 fails to resolve sqlx-core dep