Releases: meteor-space/event-sourcing
3.1.0
New Features
- Commit save concurrency exception handling
Concurrency exceptions can occur in a race condition where two messages are
attempting to change the state of an aggregate instance. This can often be
resolved by simply re-handling the message, which is what the Router now
does if this exception bubbles up during the save operation.
This should be safe from endless loops, because if the aggregate's state
has since changed rendering the message now invalid, a domain exception
will be thrown, which is handled elsewhere being an application concern. - New index
{ "_id": 1, "receivers.appId": 1 }
on commits collection to
optimise commit publishing. projectionRebuilder.rebuild
now returns a response object containing an
error and result, which the former will be null if no non-fatal errors were
thrown. The result contains a message and duration property.ProjectionRebuilder
now logs detailed debug information, and two info
updates to provide feedback at the desired level.
Changes
- Commits made in other apps will now only be processed if they contain
messages with registered handlers in the current app. Prior to every
commit would be returned by the observer, and then it was decided to
publish/send, or ignore. This changes the outcome of adding handlers
in to existing messages, as it will process all from the start of the store,
which may or may not be desired. It's up to the application to control this
but is now more flexible and the system can be brought up to a consistent
state as if the handlers were in place the whole time. Consider this
carefully! - Logging has been made more production-friendly, pushing some of the noisy
info
entries from the commit call down todebug
. In effect, you could logdebug
to
a local file and rotate as needed, andinfo
to an external system that gives you
the system-level updates rather than every action being taken. eventCorrelationProperty
of processes are now converted to a string if a Guid.ProjectionRebuilder
gracefully handles errors, reapplying the backup and resetting
telling the projection toexitRebuildMode
before re-throwing the error.
Future breaking, now depreciated
commitPublisher.publishCommit(commit)
now usecommitPublisher.publishChanges(changes, commitId)
Bug Fixes
- Commit processing timeout had a bug that caused the publisher to fail
commits that most likely had already been fully processed, due to the timeout
reference being lost. Failing a commit that has already
been processed was causing the commit records to be left in an invalid state.
This fix also places a guard to protect against
race conditions in the event of a genuine timeout, or redelivery via the
infrastructure. - Now the repository only calls
aggregate.replayHistory
if there have been
events since the last snapshot. - Fixes a non-critical bug with the Snapshotter where every new aggregate
instance would have the snapshot generated after the commit is added rather
than waiting for the version specified in configuration. This is a
performance improvement, particularly for batch importing.
3.0.1
Changes to projection rebuilder
Space.eventSourcing.ProjectionRebuilder
is no longer throwing an error if there is no data to insert into collection after rebuilding is done. Info message is now logged instead.
3.0.0
3.0.0
New Features
Snapshotting upgrade
-
Now handled by the module automatically, default to caching the state every 10 versions.
-
Configure using:
Configuration.eventSourcing.snapshotting.enabled = true
or
SPACE_ES_SNAPSHOTTING_ENABLED='true'
Configuration.eventSourcing.snapshotting.frequency = 20
or
SPACE_ES_SNAPSHOTTING_FREQUENCY=20
SPACE_ES_SNAPSHOTTING_COLLECTION_NAME='my_collection'
New helpers
Aggregate::_eventPropsFromCommand(command)
is an internal helper function
eliminating the boilerplate of mappingtargetId
from the command tosourceId
and manually setting theversion
prop.
Module
- This package now mixes in specific interfaces
Routers
andProjections
for better clarity in your modules/application that depends on Space.eventSourcing.
Router
Events can be automatically routed to processes and aggregates based on a correlation
property, negating the need for lookup collections:
Space.eventSourcing.Router.extend(Space.accounts, 'RegistrationsRouter', {
aggregate: Space.accounts.Registration,
initializingCommand: Space.accounts.Register,
routeEvents: [
Space.accounts.UserCreated,
Space.accounts.UserCreationFailed,
Space.accounts.AccountCreated
],
eventCorrelationProperty: 'registrationId'
});
Commit Publisher
The state of any Commit Publish action is now being managed, with any errors
thrown while processing are caught and used to fail the attempt.
There's also a timeout option to autofail the attempt in the case where a
problem occurs without an error being thrown. This defaults to 60 seconds
but can be configured using the ENV or Module Config APIs
SPACE_ES_COMMIT_PROCESSING_TIMEOUT=2000
or
Configuration.eventSourcing.commitProcessing.timeout = 2000
Domain Error handling
Now when domain exceptions are thrown in an aggregate, the router publishes a
special event Space.domain.Exception
that can be subscribed to and used for
process integration. The event has two custom properties thrower
and error
.
Breaking Changes
- Must be running Meteor 1.2.0.1 or later.
Dependencies forcing API changes
- This version uses space:base 4.x which includes breaking changes.
Please see the changelog. - This version uses space:messaging 3.x which includes breaking changes.
Please see the changelog.
Commits Collection
- Module now manages the commits collection
- Instead of passing in a collection, use the Configuration and/or ENVs.
- Default collection name has been changed from space_cqrs_commitStore
- Events are now persisted in a query-friendly format! Prior to this the data was
stored in a JSON string which was optimal for persistence, but you would have to
maintain a projection in order to query the historical data. Moving from 2.x to
3.x will require data migration, but we feel this was necessary and will be
worthwhile for the huge gain in querying capability.
Projector
and Projection
API changes
Projector
=>ProjectionRebuilder
ProjectionRebuilder::replay(options)
=>rebuild(projections, options)
Projection::enterReplayMode()
=>enterRebuildMode()
Projection::exitReplayMode()
=>exitRebuildMode()
Thanks to all the new people on the team who made this awesome release possible:
👏