developing microservices with aggregates (melbourne)
TRANSCRIPT
![Page 1: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/1.jpg)
@crichardson
Developing Microservices with Aggregates
Chris Richardson
Founder of Eventuate.io Founder of the original CloudFoundry.com Author of POJOs in Action
@crichardson [email protected] http://eventuate.io
![Page 2: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/2.jpg)
@crichardson
Presentation goal
Show how Domain Driven Design Aggregates
and Microservices are a perfect match
![Page 3: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/3.jpg)
@crichardson
About Chris
![Page 4: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/4.jpg)
@crichardson
About Chris
Consultant and trainer focusing on modern
application architectures including microservices
(http://www.chrisrichardson.net/)
![Page 5: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/5.jpg)
@crichardson
About Chris
Founder of a startup that is creating an open-source/SaaS platform
that simplifies the development of transactional microservices
(http://eventuate.io)
![Page 6: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/6.jpg)
@crichardson
For more information
http://learnmicroservices.io
![Page 7: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/7.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 8: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/8.jpg)
@crichardson
The Microservice architecture tackles complexity through
modularization
![Page 9: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/9.jpg)
@crichardson
Microservice =
Business capability
![Page 10: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/10.jpg)
@crichardson
Microservice architecture
Browser
Mobile Device
Store Front UI
API Gateway
Catalog Service
Review Service
Order Service
… Service
Catalog Database
Review Database
Order Database
… Database
HTML
REST
REST
Database per service
![Page 11: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/11.jpg)
@crichardson
But there are challenges…
![Page 12: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/12.jpg)
@crichardson
Product service
Customer serviceOrder service
Domain model = tangled web of classes
Order
OrderLine Item
quantity
…
Addressstreet city …
Customer
Productname price
?
?
creditLimit
![Page 13: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/13.jpg)
@crichardson
Reliance on ACID transactions to enforce invariantsBEGIN TRANSACTION … SELECT ORDER_TOTAL FROM ORDERS WHERE CUSTOMER_ID = ? … SELECT CREDIT_LIMIT FROM CUSTOMERS WHERE CUSTOMER_ID = ? … INSERT INTO ORDERS … … COMMIT TRANSACTION
Simple and ACID
![Page 14: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/14.jpg)
@crichardson
But it violates encapsulation…BEGIN TRANSACTION … SELECT ORDER_TOTAL FROM ORDERS WHERE CUSTOMER_ID = ? … SELECT CREDIT_LIMIT FROM CUSTOMERS WHERE CUSTOMER_ID = ? … INSERT INTO ORDERS … … COMMIT TRANSACTION
Private to the Order Service
Private to the Customer Service
![Page 15: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/15.jpg)
@crichardson
.. and requires 2PCBEGIN TRANSACTION … SELECT ORDER_TOTAL FROM ORDERS WHERE CUSTOMER_ID = ? … SELECT CREDIT_LIMIT FROM CUSTOMERS WHERE CUSTOMER_ID = ? … INSERT INTO ORDERS … … COMMIT TRANSACTION
![Page 16: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/16.jpg)
@crichardson
2PC is not an optionGuarantees consistency
BUT
2PC coordinator is a single point of failure
Chatty: at least O(4n) messages, with retries O(n^2)
Reduced throughput due to locks
Not supported by many NoSQL databases (or message brokers)
CAP theorem ⇒ 2PC impacts availability
….
![Page 17: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/17.jpg)
@crichardson
Doesn’t fit with the NoSQL DB “transaction” model
![Page 18: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/18.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 19: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/19.jpg)
@crichardson
Domain Driven Design - building blocks
Entity
Value object
Services
Repositories
Aggregates
Adopted
Ignored (at least by me)
![Page 20: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/20.jpg)
About AggregatesCluster of objects that can be treated as a unit
Graph consisting of a root entity and one or more other entities and value objects
Typically business entities are Aggregates, e.g. customer, Account, Order, Product, ….
Order
OrderLine Item
quantity productId productName productPrice
customerId
Address
street city …
![Page 21: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/21.jpg)
Aggregate: rule #1
Reference other aggregate roots via
identity
(primary key)
Order
OrderLine Item
quantity productId productName productPrice
customerId
Address
street city …
![Page 22: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/22.jpg)
@crichardson
Foreign keys in a Domain Model?!?
![Page 23: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/23.jpg)
@crichardson
Domain model = collection of loosely connected aggregates
Order
OrderLine Item
quantity
…
Addressstreet city …
Customer
Productname price
![Page 24: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/24.jpg)
@crichardson
Product service
Customer serviceOrder service
Easily partition into microservices
Order
OrderLine Item
quantity
…
Addressstreet city …
Customer
Productname price
![Page 25: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/25.jpg)
@crichardson
Aggregate rule #2
Transaction =
processing one command by one aggregate
![Page 26: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/26.jpg)
@crichardson
Product service
Customer serviceOrder service
Transaction scope = service
Order
OrderLine Item
quantity
…
Addressstreet city …
Customer
Productname price
![Page 27: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/27.jpg)
@crichardson
Transaction scope =
NoSQL database “transaction”
![Page 28: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/28.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 29: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/29.jpg)
@crichardson
Customer management
How to maintain data consistency between aggregates?
Order management
Order Service
placeOrder()
Customer Service
updateCreditLimit()
Customer
creditLimit ...
has ordersbelongs toOrder
total
Invariant: sum(open order.total) <= customer.creditLimit
?
![Page 30: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/30.jpg)
@crichardson
Saga
Using event-driven Sagas instead of 2PCDistributed transaction
Order Customer
Local transaction
Order
Local transaction
Customer
Local transaction
Order
Event Event
![Page 31: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/31.jpg)
@crichardson
Order Service
Saga-based, eventually consistent order processing
Customer Service
Order created
Credit Reserved
Credit Check Failed
Create Order
OR Customer
creditLimit creditReservations ...
Order
state total …
approve()/reject()
Event Handler
Event Handler
reserveCredit()
![Page 32: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/32.jpg)
@crichardson
Order ServiceOrder
id : 4567 total: 343 state = CREATED
Customer Service
Customer creditLimit : 12000 creditReservations: {}
Customer creditLimit : 12000 creditReservations: { 4567 -> 343}
Order id : 4567 total: 343 state = APPROVED
Eventually consistent credit checking
Message Bus
createOrder()
Publishes:Subscribes to:
Subscribes to:
publishes:
OrderCreatedEvent
CreditReservedEvent
OrderCreatedEvent CreditReservedEvent
![Page 33: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/33.jpg)
@crichardson
Complexity of compensating transactions
ACID transactions can simply rollback
BUT Developer must write application logic to “rollback” eventually consistent transactions
For example:
CreditCheckFailed => cancel Order
Money transfer destination account closed => credit source account
Careful design required!
![Page 34: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/34.jpg)
@crichardson
How atomically update database and publish an event
Order Service
Order Database
Message Broker
insert Order
publish OrderCreatedEvent
dual write problem
?
![Page 35: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/35.jpg)
@crichardson
Failure = inconsistent system
Order Service
Order Database
Message Broker
insert Order
publish OrderCreatedEvent
X
![Page 36: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/36.jpg)
@crichardson
2PC is not an option
![Page 37: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/37.jpg)
@crichardson
Reliably publish events when state changes
![Page 38: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/38.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 39: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/39.jpg)
@crichardson
Event sourcing = event-centric persistence
Application
Database
Event store
update
publish
X
![Page 40: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/40.jpg)
@crichardson
Event sourcing
For each DDD aggregate:
Identify (state changing) domain events
e.g. use Event Storming
Define Event classes
For example, Order events: OrderCreated, OrderCancelled, OrderApproved, OrderRejected, OrderShipped
![Page 41: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/41.jpg)
@crichardson
Persists events NOT current state
Order
status ….
101 ACCEPTED
Order tableX
![Page 42: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/42.jpg)
@crichardson
Event-centric schema
![Page 43: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/43.jpg)
@crichardson
Persists events NOT current state
Event table
Entity type Event id
Entity id
Event data
Order 902101 …OrderApproved
Order 903101 …OrderShipped
Event type
Order 901101 …OrderCreated
![Page 44: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/44.jpg)
@crichardson
Replay events to recreate state
Order
state
OrderCreated(…) OrderAccepted(…) OrderShipped(…)
Events
Periodically snapshot to avoid loading all events
![Page 45: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/45.jpg)
@crichardson
The present is a fold over history
currentState = foldl(applyEvent, initialState, events)
![Page 46: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/46.jpg)
@crichardson
Event Store
Application architecture
Order 123 Customer 456
OrderCreated OrderApproved …
CustomerCreated CustomerCreditReserved …
CreateOrder UpdateOrder GetOrder
Subscribe
Order Service
CreateCustomer UpdateCustomer GetCustomer
Subscribe
Customer Service
![Page 47: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/47.jpg)
@crichardson
Request handling in an event sourced application
HTTP Handler
Event Store
pastEvents = findEvents(orderId)
Order
new()
applyEvents(pastEvents)
newEvents = processCmd(someCmd)
saveEvents(newEvents) (optimistic locking)
Order Service
applyEvents(newEvents)
![Page 48: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/48.jpg)
@crichardson
Event Store publishes events consumed by other services
Event Store
Event Subscriber
subscribe(EventTypes)
publish(event)
publish(event)
Customer
update()
Customer Service
![Page 49: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/49.jpg)
@crichardson
Event Store publishes events consumed by other services
Event Store
Event Subscriber
subscribe(EventTypes)
publish(event)
publish(event)
CQRS View
update()
Service Xyz
send notifications
…
![Page 50: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/50.jpg)
Event store = database + message broker
Home grown/DIY
.NET geteventstore.com
https://www.lightbend.com/lagom
http://eventuate.io (mine)
…
Event Store
Save aggregate
events
Get aggregate
events
Subscribe to events
![Page 51: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/51.jpg)
@crichardson
Benefits of event sourcingSolves data consistency issues in a Microservice/NoSQL based architecture
Reliable event publishing: publishes events needed by predictive analytics etc, user notifications,…
Eliminates O/R mapping problem (mostly)
Reifies state changes:
Built in, reliable audit log
temporal queries
Preserved history ⇒ More easily implement future requirements
![Page 52: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/52.jpg)
@crichardson
Drawbacks of event sourcing…
Requires application rewrite
Weird and unfamiliar style of programming
Events = a historical record of your bad design decisions
Must detect and ignore duplicate events
Idempotent event handlers
Track most recent event and ignore older ones
…
![Page 53: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/53.jpg)
@crichardson
… Drawbacks of event sourcing
Querying the event store can be challenging
Some queries might be complex/inefficient, e.g. accounts with a balance > X
Event store might only support lookup of events by entity id
Must use Command Query Responsibility Segregation (CQRS) to handle queries ⇒ application must handle eventually consistent data
![Page 54: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/54.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 55: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/55.jpg)
@crichardson
Orders and Customers example
Kafka
Rest API
Event Store
Event Store
Adapter
Customer Service
Rest APIOrder Service
Customer Aggregate
Order Aggregate
Rest APIOrder HistoryService
MongoDB
CQRS View
Event Store
Adapter
Event Store
Adapter
Used to notify Order Service of invalid
customer ids!
![Page 56: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/56.jpg)
@crichardson
Customer microservice
Customer Service
CustomerController
Spring Cloud
StreamKafka
Customer Aggregate
Rest API
Customer Event Handlers
EventStore
Event Store
Adapter
Order*Event
POST /customers
![Page 57: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/57.jpg)
@crichardson
The Customer aggregate
Money creditLimit Map<OrderId, Money> creditReservations
Customer
List<Event> process(CreateCustomerCommand cmd) { … } List<Event> process(ReserveCreditCommand cmd) { … } … void apply(CustomerCreatedEvent anEvent) { … } void apply(CreditReservedEvent anEvent) { … } …
State
Behavior
![Page 58: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/58.jpg)
@crichardson
Familiar concepts restructured
class Customer {
public void reserveCredit( orderId : String, amount : Money) {
// verify
// update state this.xyz = … }
public List<Event> process( ReserveCreditCommand cmd) { // verify … return singletonList( new CreditReservedEvent(…); ) }
public void apply( CreditReservedEvent event) { // update state this.xyz = event.xyz }
![Page 59: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/59.jpg)
@crichardson
Customer command processing
![Page 60: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/60.jpg)
@crichardson
Customer applying events
![Page 61: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/61.jpg)
@crichardson
Customer Controller
![Page 62: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/62.jpg)
@crichardson
Creating a Customer
save() concisely specifies: 1.Creates Customer aggregate 2.Processes command 3.Applies events 4.Persists events
![Page 63: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/63.jpg)
@crichardson
Event handling in CustomersDurable subscription name
1. Load Customer aggregate 2. Processes command 3. Applies events 4. Persists events
Triggers BeanPostProcessor
Publish message to Spring Cloud Stream (Kafka) when Customer not found
![Page 64: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/64.jpg)
@crichardson
Event handler in Orders
![Page 65: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/65.jpg)
@crichardson
Agenda
The problem with Domain Models and microservices
Overview of aggregates
Maintaining consistency between aggregates
Using event sourcing with Aggregates
Customers and Orders example
Using explicit saga orchestration
![Page 66: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/66.jpg)
@crichardson
Order Service
Order Service ⬄ Customer Service: tightly coupled, cyclic dependency 😢
Customer Service
Order created
Credit Reserved
Credit Check FailedOR
Must subscribe to all Order events that
affect available credit!Order …
![Page 67: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/67.jpg)
@crichardson
Order Service
Decouple by maintaining available credit in OrderService
Customer ServiceAvailable Credit Changed
Customer CreatedCustomer
creditLimit availableCredit ...
Order
state total …
AvailableCredit Tracker
creditLimit availableCredit ...
Simpler 😄 Still cyclic 😢
![Page 68: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/68.jpg)
Use an explicit sagaSaga object that orchestrates the flow
Created in response to an initial event, e.g. OrderCreated
A state machine
Receives events from aggregates
Sends commands to aggregates
Implemented as an event-sourced aggregate
Saga
Event
Command
![Page 69: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/69.jpg)
@crichardson
Customer Service
Order Service
Using an OrderCreationSaga
Order
state total …
AvailableCredit Tracker
creditLimit availableCredit ...
Order Creation
Saga
create()create()
Reserve Credit
Credit Reserved
Approve Order
Customer
Update Available
Credit
OrderCreated
Acyclic 😄
![Page 70: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/70.jpg)
@crichardson
Order saga state machine
NEW
SUCCEEDED
FAILED
OrderCreatedEvent/ reserveCredit()
CustomerCreditReservedEvent /approveOrder()
EntityNotFoundCommandExecutionErrorCustomerCreditLimitExceededEvent /
rejectOrder()
![Page 71: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/71.jpg)
@crichardson
Saga as a singleton state machine State + Data
(State, Data, Event) ⇒
(Commands, State’, Data’)
![Page 72: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/72.jpg)
@crichardson
(OrderSagaState, OrderSagaData, Event) ⇒
(Commands, OrderSagaState’, OrderSagaData’)
![Page 73: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/73.jpg)
@crichardson
OrderCreationSaga: (state, event) ⇒ (commands, state’)
![Page 74: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/74.jpg)
@crichardson
Initial actionStarting action
Triggers saga creation
1. Send command 2. Transition to new state 3. Create data
![Page 75: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/75.jpg)
@crichardson
Event handlerCurrent state
Triggering event
1. Send command 2. Transition to new state
![Page 76: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/76.jpg)
@crichardson
Kafka-based command bus
Order Saga
Credit Tracking
Aggregate
CreditTrackingCommand Topic
OrderSagaCommandFailure Topic
Reserve Credit
CustomerNotFound
Per aggregate
type
Per saga type
![Page 77: Developing microservices with aggregates (melbourne)](https://reader033.vdocuments.mx/reader033/viewer/2022042907/58ce63841a28ab2f268b5fbd/html5/thumbnails/77.jpg)
@crichardson
Summary
Aggregates are the building blocks of microservices
Use event-driven sagas to maintain consistency between aggregates
Event sourcing is a good way to implement a event-driven architecture
Use explicit sagas to orchestrate transactions