Domain Events
Files Referenced in this Document
- MyEntityNameEto.cs
- MyEntityNameEventHandler.cs
- MyEntityName.cs
- CMSPluginDomainModule.cs
- CMSPluginDomainSharedModule.cs
Table of Contents
- Introduction
- MyEntityNameEto Event Transfer Object
- MyEntityNameEventHandler Event Handler
- Domain Event Publishing Mechanism
- Advantages of Event-Driven Architecture
- Summary and Development Guide
Introduction
This document comprehensively explains the event-driven mechanism in the MyEntityName domain. Based on a distributed event bus, this mechanism implements loosely coupled communication across service boundaries by defining Event Transfer Objects (ETOs) and event handlers. The document details event definition, handling, publishing flows, and advantages in ensuring eventual system consistency.
MyEntityNameEto Event Transfer Object
MyEntityNameEto is the Event Transfer Object (ETO) for the MyEntityName domain, used to transfer data related to the MyEntityName entity across service boundaries in a distributed system.
Key features of this object include:
- Immutability: Its
Nameproperty is initialized only in the constructor and is read-only externally, ensuring integrity of event data during transmission. - Serialization Support: The class is marked with
[Serializable], enabling serialization and deserialization over the network, which is the foundation for distributed event transmission. - Single Data Carrier: Currently contains only the
Nameproperty as the core information to broadcast when the event occurs.
This design pattern ensures clarity, stability, and transportability of event data.
Section sources
MyEntityNameEventHandler Event Handler
MyEntityNameEventHandler is the concrete implementation class responsible for handling MyEntityNameEto events.
Key implementation details of this handler:
- Event Subscription: By implementing the
IDistributedEventHandler<MyEntityNameEto>interface, this handler automatically subscribes to distributed events of typeMyEntityNameEto. ItsHandleEventAsyncmethod is called when such events are published on the event bus. - Lifecycle Management: Implements
ITransientDependencyinterface, indicating a transient lifecycle. A new instance is created for each event processing, ensuring independence and thread safety. - Async Processing:
HandleEventAsyncuses an asynchronous pattern, meeting modern application requirements for high concurrency and non-blocking I/O. - Empty Implementation Status: Currently, the
HandleEventAsyncbody is empty (return Task.CompletedTask;), providing an extension point for developers. Developers should add specific business logic here, such as:- Sending notifications (e.g., email, SMS)
- Updating caches to maintain data consistency
- Triggering downstream service business processes
- Recording audit logs
Section sources
Domain Event Publishing Mechanism
Domain event publishing follows standard patterns in Domain-Driven Design (DDD), mainly involving two core steps: Defining events in the Aggregate Root and Publishing events by Domain Services.
-
Defining events in the Aggregate Root: Although not directly shown in current code, standard practice involves calling
AddLocalEvent()orAddEvent()methods within business methods of theMyEntityNameaggregate root (inheriting fromFullAuditedAggregateRoot<Guid>) when important business state changes occur, adding aMyEntityNameEtoevent instance to the aggregate root's event collection. For example, after theUpdatemethod successfully modifies the entity, an event can be added to announce "MyEntityName Updated". -
Publishing events by Domain Services: When changes to the aggregate root are persisted (e.g., via repository
SaveorUpdatemethods), the framework automatically publishes accumulated domain events to the event bus. In distributed scenarios, these events are serialized and sent to message queues (like RabbitMQ, Kafka), triggering all handlers subscribed to the event (likeMyEntityNameEventHandler).
This mechanism decouples business logic execution from event publishing, ensuring purity of core business code.
Section sources
Advantages of Event-Driven Architecture
Adopting an event-driven mechanism brings significant advantages to the system, the core being Eventual Consistency.
- Eventual Consistency: In distributed systems, strong consistency (ACID) is often costly and difficult to achieve. Event-driven architecture implements eventual consistency through the "commit local transaction first, then publish event" pattern. This means that after a service completes its local data update, it immediately confirms the operation and asynchronously notifies other services. Although other services' data updates will have a short delay, the system will eventually reach a consistent state. This pattern greatly improves system response speed and availability.
- Loose Coupling: Event publishers (like
MyEntityNameaggregate root) do not need to know who consumes the event, nor interact directly with consumers (likeMyEntityNameEventHandler). This allows system components to be developed, deployed, and scaled independently. - Extensibility: New event handlers can be easily added to respond to the same event without modifying publisher code, facilitating feature extension.
- Traceability: Events themselves record important state changes occurring in the system, providing valuable data for auditing, monitoring, and troubleshooting.
Diagram sources
Summary and Development Guide
This document detailed the event-driven mechanism in the MyEntityName domain. MyEntityNameEto as an immutable, serializable data carrier, and MyEntityNameEventHandler as the event consumer, together constitute the core of event processing.
Development Guide:
- Publish Event: Create a
MyEntityNameEtoinstance and call theAddEvent()method within business methods of theMyEntityNameaggregate root when key state changes occur. - Handle Event: Fill in actual business logic in the
HandleEventAsyncmethod ofMyEntityNameEventHandler. Note exception handling and consider idempotency, as events might be consumed repeatedly. - Leverage Advantages: Fully utilize the eventual consistency and loose coupling features brought by event-driven design to build highly available, scalable distributed systems.
Section sources