TECHNICAL FEATURE SET
Domain Driven Design |
Command Sourcing |
CQRS |
Functional Reactive Programing |
Haskell
GSD is a distributed application based on the following concepts :
- Domain Driven Design (DDD)
- Place the project's primary focus on the core domain and domain logic
- Base complex designs on a model of the domain
- CQRS
- It stands for Command Query Responsibility Segregation.
- It also known as the distributed version of DDD (and then DDDD as Distributed Domain Driven Design)
- Command Sourcing ( Event Sourcing ++)
- It's Event Sourcing where commands are also persisted
- Capture all changes to an application state as a sequence of events
- Capture all the commands sent to the system
- Commands sent to the system are stored and consumed asynchronously as opposed to Event Sourcing
- Command losses are reduced when the service is down
- The data flow is pulled as opposed to pushed in Event Sourcing
- Processes are embedded in a stream from A-Z
- This command consumption produces and stores a single transaction :
- It's Event Sourcing where commands are also persisted
data CommandHandlingResult = CommandRejected { reason :: RejectionReason}
| CommandValidated { events :: [Event]}
data CommandTransaction = CommandTransaction {
commandId :: CommandId,
commandOffset :: Offset ,
aggregateId :: AggregateId ,
commandHandlingResult :: CommandHandlingResult }- Functional Reactive Programing
- it's a programming paradigm for reactive programming (asynchronous dataflow programming) using the building blocks of functional programming (e.g. map, reduce, filter).
- Streams and Logs (FIFO) are natural DDDD Architecture Building Blocks.
- Micro-service Architecture
- Services are small in size
- Messaging enabled
- Bounded by contexts
- Autonomously developed
- Independently deployable
- Decentralized
- Built and released with automated processes.
All these concepts are building blocks for implementing the Kahn process networks (KPNs, or process networks). They are a concurrent model of computation which can be also considered as a Pattern / Architecture for distributed systems.
Related Articles :
- https://martinfowler.com/eaaDev/EventSourcing.html
- http://www.cqrs.nu/faq
- https://thinkbeforecoding.com/post/2013/07/28/Event-Sourcing-vs-Command-Sourcing
- https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-i-of-ii/
The GSD application is made of 6 distributed services :
-
cli- Command Line Interface to pilot the system.- Send commands to the system
- Read eventually up-to-date projections from the Read service
- Read eventually up-to-date projections from a Monitoring service
-
command-sourcer- Receive commands
- Dispatch and Persist these commands
-
command-consumer- Command Consumption Orchestration (CQRS Sagas Terminology)- Listen on commands arriving on the command stream for each aggregates
- Re-build the write model from the previous command transactions
- Perform the transactions on each command persisted (
handleCommand), a command can be :- Accepted (contains events)
- Rejected (contains the reason of rejection)
- Persist these command transactions
-
gsd-read- Read from the command transaction streams
- Project a model optimised for the read
- Serve that model to the cli service
-
gsd-monitoring- Read the command transaction and the command streams
- Project a model optimised for monitoring the system
- Serve that model to the cli service
-
eventstore-service- embedded into a docker container- Implement the
PersistedStreamEngineinterface . - Persist and give access to Logs
- Implement the
Each service is safe and can only be terminated by
- a SIG-INT (releasing resources properly)
- a SIG-KILL
Each service has a built-in bootstrap health-check mechanism and come back in that mechanism whenever it becomes unhealthy.
- Regarding the GSD application
-
cliis healthy, when the following dependencies are healthy :command-sourcercommand-consumergsd-readgsd-monitoring
-
command-sourceris healthy, wheneventstore-serviceis healthy -
command-consumeris healthy, wheneventstore-serviceis healthy -
gsd-readis healthy, wheneventstore-serviceis healthy -
gsd-monitoringis healthy, wheneventstore-serviceis healthy
-
Eventuria is the name of the company hosting the project (root package). By flicking through the codebase under Eventuria, you'll see the following packages :
-
Adapters: Contains wrappers, tweaks on external libraries -
Commons: Tiny Bounded Contexts -
GSD: GSD Application Bounded Context, you'll find the 4 services cited previously in that docCLI:gsd-cliimplementationWrite:gsd-command-consumergsd-command-sourcer
Read:gsd-readimplementationMonitoring:gsd-monitoringimplementation
-
CQRS: CQRS Bounded Context (this Library will eventually become a Framework - see Emergent CQRS framework Section )PersistedStreamEngine- Interface for Reading/Subscribing/Writing messages to Logs (persisted streams)
- Contain one instance for the EventStore
All these packages will eventually be in their own git repository as they get more mature.
command-sourcer- Handle an Aggregate index (AggregateId Stream)
- Serve Command Requests - Feed the Command Streams (1 Command Stream per Aggregate)
command-consumer- Per aggregate :- Subscribe to Commands
- Project a write Model
- Handle each command by providing a Command Transaction :
- Accepted (contains events)
- Rejected (contains the reason of rejection)
- Feed the Command Transaction Stream
gsd-read- Read a Command Transaction Stream
- Project from command transaction to a specific read model
- Serve clients with this model
gsd-monitoring- Read a Command Transaction Stream
- Project from command transaction to a specific read model
- Serve clients with this model
One of the intents when starting this project was to formalize the CQRS pattern and get eventually a Framework out of a concrete application like GSD. This is what the package Eventuria.CQRS will eventually become...
To use this framework, the GSD application provides the following :
- a specific WriteModel (GSD
WriteModel) - a map between the application and CQRS events (GSD
Commands) - a map between the application and CQRS commands (GSD
Events) - a Command Consumption Orchestration (GSD
Orchestration) - 2 functions (
ProjectWriteModelandHandleCommand)data CommandHandlingResult = CommandRejected { reason :: RejectionReason} | CommandValidated { events :: [Event]} type ProjectWriteModel writeModel = Maybe writeModel -> CommandHandlingResult -> Maybe writeModel type HandleCommand writeModel = Maybe writeModel -> (Persisted Command) -> IO (CommandHandlingResult)
- GSD
ProjectWriteModel - GSD
HandleCommand



