@coderbyheart/aws-dynamodb-es-cqrs
v1.3.0
Published
ES/CQRS using AWS DynamoDB
Readme
aws-dynamodb-es-cqrs · ES/CQRS using AWS DynamoDB 
Events
- Events are described by
AggregateEvent(ULID-basedeventId,aggregateName,aggregateId,aggregateVersion,actorId). - Aggregate metadata:
AggregateMetawithid,version,actorId, optionalupdatedAt.
- Events are described by
Reducing events to aggregates (Event Sourcing)
- Generic reducer:
reduceEventsapplies a sequence ofAggregateEventto produce an aggregate state. - Domain reducer example (BlogPost):
blogPostReduceruses type guards (isNamedEvent) and assertions (assertAggregateEvent) to evolve state from events.
- Generic reducer:
Commands (write side)
- Commands validate current state and produce new events:
- Create:
createBlogPostCommand - Publish:
publishBlogPostCommand - Update title:
updateBlogPostTitleCommand
- Create:
- Concurrency and existence are enforced using:
ConflictErrorandNotFoundError- Version checks against the loaded aggregate before emitting the next event.
- Commands validate current state and produce new events:
Persistence (event store + aggregate projection)
- DynamoDB persistence is transactional to keep aggregate and event store in
sync:
persistDynamoDBperforms a TransactWrite that:- Upserts the aggregate row with optimistic concurrency:
- New aggregate:
attribute_not_exists(aggregateId)(version 1). - Update:
#version = :prevVersionand setsupdatedAt.
- New aggregate:
- Writes the event into the events table.
- Upserts the aggregate row with optimistic concurrency:
- Aggregate unmarshalling for reads:
unmarshallAggregate.
- Event queries:
- List an aggregate’s events:
listAggregateEventsDynamoDB - Parse DynamoDB Streams records back into events:
extractEventsFromDynamoDBEvent
- List an aggregate’s events:
- DynamoDB persistence is transactional to keep aggregate and event store in
sync:
Queries (read side)
- Read the current aggregate projection:
- Example (BlogPost):
- Read the current aggregate projection:
Setup
Install the dependencies:
npm ciTests
The test folder contains an example aggregate (a blog post), and
operations that manipulate it, which demonstrate how the key components of this
implementation work with separate read/write components demonstrating create,
read aggregate, list events, and optimistic concurrency.
Install DynamoDB (local)
wget https://s3.eu-central-1.amazonaws.com/dynamodb-local-frankfurt/dynamodb_local_latest.zip
unzip dynamodb_local_latest.zip -d ./dynamodb_local_latestStart it in background:
java -Djava.library.path=./dynamodb_local_latest/DynamoDBLocal_lib -jar ./dynamodb_local_latest/DynamoDBLocal.jar -sharedDb -inMemory &Run the tests:
npm test