Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of handling domain events requires improvement. #43392

Open
voroninp opened this issue Nov 9, 2024 · 0 comments
Open

Example of handling domain events requires improvement. #43392

voroninp opened this issue Nov 9, 2024 · 0 comments
Labels
dotnet-architecture/svc microservices/subsvc Pri1 High priority, do before Pri2 and Pri3 ⌚ Not Triaged Not triaged

Comments

@voroninp
Copy link
Contributor

voroninp commented Nov 9, 2024

Type of issue

Missing information

Description

The section The deferred approach to raise and dispatch events is missing some vital details.

First, the comment in this code fragment is misleading:

public class OrderingContext : DbContext, IUnitOfWork
{
    // ...
    public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))
    {
        // Dispatch Domain Events collection.
        // Choices:
        // A) Right BEFORE committing data (EF SaveChanges) into the DB. This makes
        // a single transaction including side effects from the domain event
        // handlers that are using the same DbContext with Scope lifetime
        // B) Right AFTER committing data (EF SaveChanges) into the DB. This makes
        // multiple transactions. You will need to handle eventual consistency and
        // compensatory actions in case of failures.
        await _mediator.DispatchDomainEventsAsync(this);

        // After this line runs, all the changes (from the Command Handler and Domain
        // event handlers) performed through the DbContext will be committed
        var result = await base.SaveChangesAsync();
    }
}

This makes a single transaction including side effects from the domain event handlers that are using the same DbContext with Scope lifetime.

This statement is not correct because by default each call to SaveChanges is wrapped in its own transaction. The first handler to call SaveChanges will save both its own changes and the changes that lead to the event. Subsequent handlers will persist changes in separate transactions.
For this to work the Application layer must open and commit transaction; Only in this case all calls to SaveChanges will belong to it.

Second, handling domain events immediately after committing the transaction without an outbox should be a deliberate decision when risks are known and accepted, so it's worth mentioning at least.

Also, choosing for eventual consistency between aggregates effectively turns them into actors and somewhat blures the border between domain and integration events. IMO, the main distinction between domain and integration events is how much contract coupling is still fine. Domain events within single bounded context are safer regarding exposing more details. Sometimes single bounded context can be served by multiple physical nodes, so in-memory mediator won't work anyway, and proper message bus will be required.

Page URL

https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation#the-deferred-approach-to-raise-and-dispatch-events

Content source URL

https://github.com/dotnet/docs/blob/main/docs/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation.md

Document Version Independent Id

e41af96d-f015-a8e0-4449-7a508d7bccc8

Article author

@jamesmontemagno

Metadata

  • ID: d432d5bb-24a7-3bec-1e17-910c8129226e
  • Service: dotnet-architecture
  • Sub-service: microservices

Related Issues

@issues-automation issues-automation bot added dotnet-architecture/svc microservices/subsvc Pri1 High priority, do before Pri2 and Pri3 labels Nov 9, 2024
@dotnetrepoman dotnetrepoman bot added the ⌚ Not Triaged Not triaged label Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dotnet-architecture/svc microservices/subsvc Pri1 High priority, do before Pri2 and Pri3 ⌚ Not Triaged Not triaged
Projects
None yet
Development

No branches or pull requests

1 participant