10. CARGO TRACKER
REFACTORING - DELIVERY HISTORY
▸ “leaves Delivery History with no persistent state”
▸ “no real need to keep it around”
▸ “we could derive Delivery History itself whenever it is
needed to answer some question”
11. CARGO TRACKER
REFACTORING - HANDLING EVENT AGGREGATE
▸ HandlingEvent Aggregate:
▸ no domain logic (anemic)
▸ only repository + event class
▸ repository servicing query needs of other aggregates
24. CQRS RECAP
SYNC PROCESSING
▸ single process (e.g. Web App)
▸ decreases availability
▸ if process is UI affects UX
▸ in-process event dispatcher for decoupling
▸ rely on base framework facilities
▸ immediate consistency
25. CQRS RECAP
ASYNC PROCESSING
▸ multiple processes (e.g. WebApp and WorkerApp)
▸ higher availability, scaling out
▸ consistency eventual
▸ typically implemented with async messaging
▸ message bus
▸ in-process event dispatcher allows for applying selectively
26. CQRS RECAP
TYPICAL SYSTEM with CQRS + ASYNC PROCESSING
/ *
-BBB
3
B BB #
/ A A *
3 BB # 3 A
A BC A B A C A C B BC C
B 2 3
AB BCB BC C CB
B B A B B CB
C
B BB #
B 3B C 2 3 A B C A 3 3
. 3 - 3
C
2 B BC C#
/ A A * (
3 A A
A 2 BB C
3 AB#
C A 2 BB# C
B B2A A#
/ A A * )
2 ACB CB
C A 3 3
2CB 3 AB BCB
/A C 3
28. ASYNC MESSAGING
MESSAGE BUS 1/2
▸ frameworks: NServiceBus, MassTransit, Rebus etc.
▸ transports: RabbitMQ, Azure Service Bus etc.
▸ at least-once delivery
▸ FIFO
▸ reliable messaging
▸ automatic transport configuration setup
▸ pub/sub, send/receive
29. ASYNC MESSAGING
MESSAGE BUS 1/2
▸ frameworks: NServiceBus, MassTransit, Rebus etc.
▸ transports: RabbitMQ, Azure Service Bus etc.
▸ at least-once delivery
▸ FIFO
▸ reliable messaging
▸ automatic transport configuration setup
▸ pub/sub, send/receive
30. ASYNC MESSAGING
ASYNC & RELIABLE MESSAGING
ALL=CA .KI AK
N ELDAK A AK AM
N L KE AK ( A AE AK
AM
N L KE AK )
1P D= CA -
NANA ( NANA )
1P D= CA . R
)
-/3IK1KKIK
(
A
-/3IK
=
LC A E AKQ EL 142-.41 ( # , 2B
LC EL IM - A Q MDA .KI AK =
1KKIK EL K=ELA E MDA A AK
LC A E AKQ EL 142-.41 ) # , 2B LC EL IM - A IK
= A Q MDA A AE AK MDA LC LM=QL E MDA NANA
LC A E AKQ A MI
A # EL - / ,
A AK EL I A =BMAK
CAMME C MDA -
LC A E AKQ EL
142-.41 # ,
NANAL = A
AKLELMA M = KILL
KI AK KALM=KML
- = EM # 1 - 41
AAEA
31. ASYNC MESSAGING
MESSAGE BUS 2/2
▸ connection management
▸ persistent sagas/process managers
▸ retrying policy on subscriber/receiver errors
▸ alarm service
▸ (de)serialization
56. IMPLEMENTATION
MASSTRANSIT RETRING FLOW (SIMPLIFIED)
1. message deserialised
2. identity consumer from message type
A. if consumer identified
‣ run handler in try/catch
‣ on exception check retry policy
‣ either retry on ignore
B. if consumer is NOT identified (TbC)
62. IMPLEMENTATION
EVENT DISPATCHER 1/2
▸ wires SYNChronously (in-process) command with event handlers
▸ is the “Emitter”
▸ wired handlers can be
▸ an actual one (e.g. read model update)
▸ forwarder (event->message + publish) to the bus
▸ both
▸ even for the same event
▸ infra free implementation
65. IMPLEMENTATION
EVENT EMITTING/PUBLISHING
▸ as with Commands, Events should use domain structures
▸ IEventEmitter abstraction similar to ICommandIssuer
▸ MassTransit implementation with Bus.Publish<T>
▸ Converts Events to Messages (TbC)
68. IMPLEMENTATION
EVENT SUBSCRIBING / BOOTSTRAPPING MASSTRANSIT
▸ bootstrapping identical to command receiving
▸ need a Consumer<T>
▸ translates the message to event
▸ instantiates and invokes event handler
75. BEST PRACTICES
MESSAGE DESIGN
▸ messages are POCOS. (period)
▸ do NOT reuse domain structures
▸ SERIOUS danger of message loss
▸ type repetition and mapping are unavoidable
▸ Automapper FTW !
▸ messages might change (aka message versioning)
▸ subscribe to interfaces
▸ ensure correct version or serialiser assembly deployed
▸ JSON .NET
76. BEST PRACTICES
SYSTEM ARCHITECTURE
▸ apply selectively not globally
▸ always forward (i.e. publish) the events
▸ bounded context interface
▸ rely on the retrying facilities
▸ idempotency
▸ fence “expensive” services
▸ perhaps even with sync send/receive (e.g. Routing Service)
77. BEST PRACTICES
SCALING OPTIONS
▸ scale up: can invoke Message Handlers in parallel using a
ThreadPool = Round Robin
▸ bus.SetConcurrencyLimit
▸ scale out: “competing consumers”
▸ same EndPointID
▸ probable concurrency issues
▸ aggregate versioning !
78. BEST PRACTICES
HOUSE-KEEPING
▸ descriptive End Point IDs mostly for subscribers/receivers
▸ web_SERVER1_sender
▸ cmd_rec_worker
▸ evt_sub_booking_reporting
▸ evt_sub_shipping
▸ monitor transport
84. CHALLENGES
EVENTUAL CONSISTENCY
▸ heavily affects UI/UX
▸ contradicts user mentality
▸ need to notify on command handling error
▸ makes UI implementation more complex
85. CHALLENGES
IMPLEMENTATION-RELATED
▸ a LOT of type repetition
▸ more physical processes
▸ changes MIGHT need orchestration
▸ concurrency issues
▸ transport = additional infra
87. RESOURCES
READINGS
▸ CQRS Journey by Microsoft Patterns & Practises
cqrsjourney.github.io
▸ CQRS by Edument
cqrs.nu
▸ Clarified CQRS by Udi Dahan
udidahan.com/2009/12/09/clarified-cqrs
▸ MassTransit Documentation
docs.masstransit-project.com
88. RESOURCES
SAMPLES
▸ Cargo Tracker
▸ github.com/citerus/dddsample-core
(Java) by Citerus AB
▸ github.com/SzymonPobiega/DDDSample.Net
(.ΝΕΤ) by Szymon Pobiega
▸ CQRS, The example - Mark Nijhof
leanpub.com/cqrs