Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • Contact Us
  • Home
  • System Architecture

Integrating Aggregates

Written by Oleksandr Sydorenko

Updated at May 5th, 2025

Contact Us

If you still have questions or prefer to get help directly from an agent, please submit a request.
We’ll get back to you as soon as possible.

Please fill out the contact form below and we will reply as soon as possible.

  • System Architecture
+ More

In Chapter 6, we discussed that one of the ways aggregates communicate with the rest of the system is by publishing domain events. External components can subscribe to these domain events and execute their logic. But how are domain events published to a message bus?

Before we get to the solution, let’s examine a few common mistakes in the event pub‐ lishing process and the consequences of each approach. Consider the following code:

01 public class Campaign

02 {

03

...

04

List<DomainEvent> _events;

05

IMessageBus _messageBus;

06

...

07

08

public void Deactivate(string reason)

09

{

10

for (l in _locations.Values())

11

{

12

l.Deactivate();

13

}

14

15

IsActive = false;

16

17

var newEvent = new CampaignDeactivated(_id, reason);

18

_events.Append(newEvent);

19

_messageBus.Publish(newEvent);

20

}

21

}

On line 17, a new event is instantiated. On the following two lines, it is appended to the aggregate’s internal list of domain events (line 18), and the event is published to the message bus (line 19). This implementation of publishing domain events is simple but wrong. Publishing the domain event right from the aggregate is bad for two rea‐ sons. First, the event will be dispatched before the aggregate’s new state is committed to the database. A subscriber may receive the notification that the campaign was deactivated, but it would contradict the campaign’s state. Second, what if the database transaction fails to commit because of a race condition, subsequent aggregate logic rendering the operation invalid, or simply a technical issue in the database? Even though the database transaction is rolled back, the event is already published and pushed to subscribers, and there is no way to retract it.

Let’s try something else:

01 public class ManagementAPI

02 {

03 ...

04 private readonly IMessageBus _messageBus;

05 private readonly ICampaignRepository _repository; 06 ...

07 public ExecutionResult DeactivateCampaign(CampaignId id, string reason) 08 {

09 try

10 {

11 var campaign = repository.Load(id);

12 campaign.Deactivate(reason);

13 _repository.CommitChanges(campaign);

14

15 var events = campaign.GetUnpublishedEvents();

16 for (IDomainEvent e in events)

17 {

18 _messageBus.publish(e);

19 }

20 campaign.ClearUnpublishedEvents();

21 }

22 catch(Exception ex)

23 {

24 ...

25 }

26 }

27 }

In the preceding listing, the responsibility of publishing new domain events is shifted to the application layer. On lines 11 through 13, the relevant instance of the Campaign aggregate is loaded, its Deactivate command is executed, and only after the updated state is successfully committed to the database, on lines 15 through 20, are the new domain events published to the message bus. Can we trust this code? No.

In this case, the process running the logic for some reason fails to publish the domain events. Perhaps the message bus is down. Or the server running the code fails right after committing the database transaction, but before publishing the events the sys‐ tem will still end in an inconsistent state, which means that the database transaction is committed, but the domain events will never be published.

These edge cases can be addressed using the outbox pattern.

Was this article helpful?

Yes
No
Give feedback about this article

Related Articles

  • Discovering Domain Knowledge
  • Business Problems
  • Knowledge Discovery
  • Communication
  • What Is a Ubiquitous Language?

info@smartphonekey.com

  • Home
  • How It Works
  • Features
  • Residents and Tenants
  • Property Managers
  • Airbnb Hosts
  • Products
  • Blog
  • Guide for Usage and Installation
  • Our Team
  • Contact Us
  • Privacy Policy
  • Terms of Service
  • Facebook
  • Instagram
  • LinkedIn
© 2025, Smartphonekey.com Powered by Shopify
Expand