Events are easy to grasp. Event Storming! Goods shipped Order placed Goods fetched Payment received „We need to achieve some facts to create value for customers!“ Events are a concept easy to grasp for everybody in the room.
Events help with cross-cutting concerns Payment received Customer Notification Policy Inform customer listened to by triggers Payment Service Notification Service
Relying on events only leads to suboptimal coupling Order placed Payment Service Payment received Inventory Service Goods fetched Shipment Service Goods shipped
Shipment Service Autonomous services can be deployed independently. To change the order of two services, we touch 4 sticky notes… but wait, all three services! Goods shipped Order placed Inventory Service Payment Service Payment received Goods fetched
Who owns the policy in a pure event choreography? Payment received Start Fetching Policy Fetch goods listened to by triggers Payment Service Inventory Service
Who owns the policy in a commanding approach? Payment received Start Fetching Policy Fetch goods listened to by triggers Payment Service Inventory Service
Extracting the policy into a mediator service Payment received Start Fetching Policy Fetch goods listened to by triggers Payment Service Inventory Service Order Service
The order as the companies core business Place order Order placed Request payment Order Service Payment received Fetch goods Goods fetched Ship goods Goods shipped “When the order is placed…” “When the payment is received…” “When the goods are fetched…” “Then we are done!” Mark order as fulfilled Order fulfilled Payment Service Inventory Service Shipment Service
Double check: what happens when we charge later? Place order Order placed Request payment Order Service Payment received Fetch goods Goods fetched Ship goods Goods shipped “When the order is placed…” “When the payment is received…” “When the goods are fetched…” “Then we are done!” Mark order as fulfilled Order fulfilled Payment Service Inventory Service Shipment Service
Trade offs! Events and commands in between services. Payment received Policy Fetch goods listened to by triggers Payment Service Inventory Service Order Service
Atomic vs. composite command execution Place order Order placed Typically we see a „command“ as the intent to change a write model... … but the customer‘s or service clients intent is often targeted at a more valuable business result, which needs many steps to be achieved. Place order Order fulfilled Atomic, trans- actional execution Composite, long- running execution
Let‘s do some event storming… Request payment Payment received Payment requested Charge credit card Depending on account balance Withdraw amount from account Amount Withdrawn Credit card charged Credit card failed Update credit card details Account details Credit card details updated Whenever card details are updated After two weeks Depending on the amount Amount credited Mark payment received Mark payment canceled Payment canceled Credit amount to account Whenever payment is canceled Mark payment received Payment received
What happens if we expose those atomic commands? Charge credit card Credit card charged Credit card failed Payment Service Retry with new credit card details Who owns the policy?
What happens if we expose troubles with some steps? Request payment Payment received Credit card failed Payment Service Retry with new credit card details Who owns the policy?
„Delegating our problems to our clients forces them to deal with the mitigation. They become god services.“ Credit card failed Retry with new credit card details Charge credit card listened to by triggers Payment Service Order Service
A long-running smart endpoint … Request payment Payment received Payment canceled 1) creates value – serving a result its client is really interested in 2) assumes responsibility – instead of delegating troubles with internal steps to its client 3) may go asynchronous – if needed for composite execution Payment Service
How do we implement the payment service? Request payment Payment received Payment requested Charge credit card Depending on account balance Withdraw amount from account Amount Withdrawn Credit card charged Credit card failed Update credit card details Account details Credit card details updated Whenever card details are updated After two weeks Depending on the amount Amount credited Mark payment received Mark payment canceled Payment canceled Credit amount to account Whenever payment is canceled Mark payment received Payment received
e.g. with Axon Messaging & Saga Management @Saga class Payment { private var paymentAmount = 0F @StartSaga @SagaEventHandler(associationProperty = "paymentId") fun on(event: PaymentRequested) { // save state, evaluate policy, create command } } Private, persistent process state Managed event correlation Process policy and construct command is cool, but Java works as well! :-)
What about business process execution engines? Monitoring & Operations Handling of time & timeouts Versatile Retries Explicitness & Visibility for Flows Versioning for Flows and Policies Transparent Compensation Parallelisation and synchronisation
Credit amount back to account Withdraw amount from cust. account Charge amount by credit card I want that kind of „reactive“ business process execution Charge amount by credit card Credit amount back to account Update credit card details Check customer account balance Payment requested Depending on account balance Charge credit card Withdraw amount from account Credit card charged Whenever credit card is charged Mark payment received Payment received Amount Withdrawn Depending on the amount Mark payment received Payment received Mark paym. partly covered Payment partly covered Whenever payment p. covered Charge credit card Credit card failed Whenever credit card failed Update credit card details Credit card details updated Whenever card details are updated Charge credit card After two weeks Mark payment canceled Payment canceled Whenever payment is canceled Credit amount to account Amount credited Every two days Remind customer Customer reminded Withdraw amount from cust. account
With this I get flexible and local technology decisions Order service Payment service Request payment Payment received Payment canceled Request payment Your local implementation reacting to events and commands
e.g. with Camunda an open source process engine Domain Entities, value objects, domain events etc… + atomic command behaviour + composite, long-running command behaviour Application Infrastructure Process Engine
Charge amount by credit card BDD style business process test - and visual feedback Charge amount by credit card Update credit card details Check customer account balance
… and I like sticky notes to discuss „what should be“! Request payment Payment received Payment requested Charge credit card Depending on account balance Withdraw amount from account Amount Withdrawn Credit card charged Credit card failed Update credit card details Account details Credit card details updated Whenever card details are updated After two weeks Depending on the amount Amount credited Mark payment received Mark payment canceled Payment canceled Credit amount to account Whenever payment is canceled Mark payment received Payment received
Need code? Reactive processes with Axon & Camunda. Order service Payment service Request payment Payment received Payment canceled Request payment plexiti de|coding domain language https://github.com/plexiti/axon-camunda-poc @martinschimak