Persisting the (last) state When persisting the structural state an event can be a transactional “by- product” of persisting a new state! The aggregate consistency is e.g. protected by transactions and optimistic locking @martinschimak
Persisting (all) the change The aggregate consistency is e.g. protected by append only logs guaranteeing unique ids With Event Sourcing events are the only persistent “source of truth”, state is dynamically derived in memory Acc. #123 increased by 10£ Acc. #123 increased by 10£ @martinschimak
#123 Cash account #654 Book 10£ for a new mouse Sync. within orig. request Network Boundary Consistency Boundary Example 3: Double Entry Accounting Potentially dangerous pattern
Unidirectional Event Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Overly Central Controllers? Sea of Events? Sharing Everything? Unidirectional Event Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On Implicit Flows?
Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On Sea of Events? Sharing Everything? Unidirectional Event Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On More Decentral Choreography Implicit Flows?
"name":"AmountCredited", "id":{ … }, … } @martinschimak Delimiting bounded contexts on moving parts ... makes sense both 1. across multiple fine-grained deployment units <= bounded context 2. within a coarse-grained monolith deployment unit > = bounded context
Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On More Decentral Choreography Sharing Everything? Unidirectional Event Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On More Decentral Choreography Explicitly Bounded Contexts Implicit Flows?
if public { "context": "BookKeeping" "name":"AccountClosed", "id":{ … } } Public integration events. Consider - a dedicated bounded context - explicit public event properties - coarse-grained summary events Public Event Bus Head over to Mathias Verraes' blog!
Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On More Decentral Choreography Explicitly Bounded Contexts Unidirectional Event Chains? Overly Vertical Decomposition? Central Reactors? Eventually Consistent eactions Event Driven Workflows Immutability and Idempotency Knowing Change Early On More Decentral Choreography Explicitly Bounded Contexts Explicit Visibility Layers Implicit Flows?
Outcome { "context": "Order" "name":"PaymentRequired", "id":{ … } } Order Payment required Language Context of Sender Billable Order generated Order placed Billable Order generated
chain" Payment Marketing Shipment Order Actor Outcome Potentially dangerous pattern "Premium customers pay after shipment" "Check identity for new customers"
to language defined by receiver! Data Flow Direction Payment Sender Receiver Language Context of Receiver Sender decides that a payment needs to be retrieved! depends on @martinschimak
sender! Order Order placed Language Context of Sender Eventual consistency Data Flow Direction depends on Sender Receiver Receiver decides that a payment needs to be retrieved! @martinschimak
Order placed on Charge credit card create Credit Card create on Payment create @martinschimak Delegation of (part of) promise Execution of promise Interpretation of observation on Consistency Boundaries Payment retrieved on Fulfillment Consequence of observation Vertical decomposition
retrieved Fulfillment Consequence of observation Payment Promote customer on Promotions Consequence of observation create Horizontal decomposition Business Capability Consistency Boundaries
Aggregate create on Aggregate create @martinschimak Consequence of observation Delegation of (part of) promise Execution of promise Interpretation of observation on Consistency Boundaries Intention on Aggregate Consequence of observation create Asynchronous and reactive aggregates
create @martinschimak Consequence of observation Delegation of (part of) promise Interpretation of observation Consistency Boundaries Intention on Aggregate Consequence of observation create A bit seldom discussed Outcome on Aggregates handling sagas and processes
card Execution of promise fun handle(intention: ChargeCreditCard): Fact { // (in real life execution would still be composite, see later) return CreditCardCharged( /* Constructor params here */ ) } @martinschimak
<Payment> { on message(RetrievePayment::class) … execute service { create intention(ChargeCreditCard::class) by { … } on message(CreditCardCharged::class) having "reference" match { paymentId } … } create success(PaymentRetrieved::class) by { PaymentRetrieved(paymentId, covered) } } @martinschimak
Clean, readable code for composite saga/process behavior + Options to execute declared state machine with different means + Automatic generation of (living, graphical) documentation + Everything needed in one place (flow, data, correlation, …) MVP coming soon! https://github.com/factdriven @martinschimak