Presented in Thessaloníki .NET Meetup. Touches on DDD Aggregates and CQRS. Shows when and how to do to async Command/Event handling with MassTransit over RabbitMQ.
4. DDD
DOMAIN MODEL
▸ structured knowledge about the domain
▸ knowledge crunching
▸ ubiquitous language
▸ typically an OO model
▸ no UI or persistence concerns
▸ != data model
5. DDD
BUILDING BLOCKS 1/2
▸ Entities
▸ id
▸ mutable
▸ Value Objects
▸ no id
▸ immutable
▸ diff state = diff value object
7. DDD
AGGREGATE
▸ object graph of Entities and Value objects
▸ root = single entity
▸ global identity
▸ external entities refer ONLY to the aggregate root
▸ root enforces invariants via root entity’s interface
▸ consistency boundary
10. CARGO TRACKER
KEY FUNCTIONALITY 1/2
▸ Book a Cargo based on Spec
▸ Get a Tracking Identifier
▸ (Re-)Assign an Itinerary
▸ Register a Handling Event (Load, Unload, Customs …)
11. CARGO TRACKER
KEY FUNCTIONALITY 2/2
▸ Get Transport Status (In Port, On Board Vessel …)
▸ Get Routing Status (Not Routed, Routed, …)
▸ Calculate Next Expected Handling Activity
▸ Get Delivery History
15. CARGO TRACKER
PROBLEMS 1/2
▸ Delivery History
▸ 1:M with Handling Events
▸ “Cargo Aggregate involved in the transaction”
▸ “ability to enter Handling Events without contention”
28. CQRS
SYNC PROCESSING
▸ single process (e.g. Web App)
▸ reduces availability
▸ affects UX
▸ in-process event dispatcher for decoupling
▸ immediate consistency
29. CQRS
ASYNC PROCESSING
▸ multiple processes (e.g. WebApp and WorkerApp)
▸ higher availability, scaling out
▸ consistency eventual
▸ also affects UX
▸ typically implemented with async messaging
▸ message bus
30. CQRS
CQRS ASYNC PROCESSING ARCHITECTURE 1/2
2 )BB
.EE3*E
A 3
3E EE3 #
2A )BB
A 3 EE3 # 3
E A E 3 3 AA E E 3
3BB E A 3
B E E E E 3
E E
3E EE3 #
- A 3 C E 3 A
3 .A
3 I
A E E #
2A )BB
A 3
B A EE
3 E#
A A B A EE#
3 #
2A )BB (
A E E
A 3 A
A E 3 B E E E
2 A
3 I
A E E #
31. CQRS
CQRS ASYNC PROCESSING ARCHITECTURE 2/2
(
C (
3 - 2 CAA B EI AC
C
B I K
CB B #
*CAA B B
C CC N
CAA B
A B
AC
AA K
CB B #
)I
B
A #
BC A
B C B
B #
CB B
B C AC
C B
C (
CI C C # B
B #
C (
M
33. 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
34. ASYNC MESSAGING
ASYNC & RELIABLE MESSAGING
CB C
2 C A C E
C C 4 C
E
C C
A
3 3
A
,.BC
CCBC
A
)
,.BC1
32 4 E 3# 2
(4
(
)
-
) =A (
3 1A (= =
== = = 3 / 3 =
D ,() , = A (
/2 3D A A A2D = A B B
3 (
) )
= = /
/
/
35. ASYNC MESSAGING
MESSAGE BUS 2/2
▸ provides
▸ transport topology setup
▸ transport connection management
▸ persistent sagas/process managers
▸ retrying policy on subscriber/receiver errors
▸ alarm service
▸ (de)serialization
48. IMPLEMENTATION
COMMAND ISSUING/SENDING SUMMARY
▸ Should use Domain Structures in Command
▸ Command Integrity
▸ ICommandIssuer abstraction
▸ MassTransit implementation
▸ Converts Commands to Messages (TbC)
▸ Encapsulate in an App Service
▸ Validation
52. 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)
55. IMPLEMENTATION
EVENT DISPATCHER 1/2
▸ wires SYNChronously (in-process) command with event handlers
▸ is the “Emitter”
▸ wired handlers can be
▸ an actual, in-process one (e.g. read model update)
▸ a forwarder (event->message + publish) to the bus
▸ both
▸ even for the same event
▸ infra free implementation
58. 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)
61. IMPLEMENTATION
EVENT SUBSCRIBING / BOOTSTRAPPING MASSTRANSIT
▸ bootstrapping identical to command receiving
▸ need a Consumer<T>
▸ translates the message to event
▸ instantiates and invokes event handler
65. BEST PRACTICES
MESSAGE DESIGN
▸ messages are POCOS. (period)
▸ do NOT reuse domain structures
▸ 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
66. 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)
67. 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
▸ UsePartitioner
▸ aggregate versioning !
70. INDICATIONS
▸ command/event handlers that are:
▸ resource intensive/blocking
▸ involve multiple aggregate instances
▸ e.g. reroute all cargos unloading @ Hong Kong
▸ error prone
▸ involve external service calls
▸ e.g. payment service
▸ multiple bounded contexts
72. CHALLENGES
EVENTUAL CONSISTENCY
▸ heavily affects UI/UX
▸ contradicts user mentality
▸ need to notify on command handling error
▸ makes UI implementation more complex
73. CHALLENGES
IMPLEMENTATION-RELATED
▸ a LOT of type repetition
▸ more physical processes
▸ changes MIGHT need orchestration
▸ concurrency issues
▸ transport = additional infra
75. RESOURCES
DDD
▸ Patterns, Principles and Practices of Domain-Driven Design by
Scott Millett, Nick Tune
http://amzn.to/2hsNbLg
▸ Domain Driven Design by Eric Evans
http://amzn.to/2uhbOSc
▸ Effective Aggregate Design (3 Part Series) by Vaughn Vernon
https://vaughnvernon.co/?p=838
▸ Awesome DDD by Nick Chamberlain
https://github.com/heynickc/awesome-ddd
76. RESOURCES
CQRS
▸ 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
77. RESOURCES
SAMPLES
▸ Cargo Tracker
▸ github.com/SzymonPobiega/DDDSample.Net
(.ΝΕΤ) by Szymon Pobiega
▸ DDD Greece Sample (TBA)
▸ CQRS, The example - Mark Nijhof
leanpub.com/cqrs