Loading aggregates on reacting to domain events - domain-driven-design

I am implementing an application with domain driven design and event sourcing. I am storing all domain events in a DomainEvents table in SQL Server.
I have the following aggregates:
- City
+ Id
+ Enable()
+ Disable()
- Company
+ Id
+ CityId
+ Enable()
+ Disable()
- Employee
+ Id
+ CompnayId
+ Enable()
+ Disable()
Each one encapsulates its own domain logic and invariants. I designed them as separate aggregates, because one city may have thousands (maybe more) companies and company may also have very large number of employees. If this entities would belong to the same aggregate I had to load them together, which in most cases would be unnecessary.
Calling Enable or Disable will produce a domain event (e.g. CityEnabled, CompanyDisabled or EmployeeEnabled). These events contain the primary key of the enabled or disabled entity.
Now my problem is a new requirement forcing me to enable/disable all related Companies if a City is enabled/disabled. The same is required for Employees, if a Company is enabled/disabled.
In my event handler, which is invoked if for example CityDisabled has occurred
I need to execute DisableCompanyCommand for each company belonging to that city.
But how would I know what companies should be affected by that change?
My thoughts:
Querying the event store is not possible, because I can't use conditions like 'where CityId = event.CityId'
Letting the parent know its child ids and putting all child ids in every event the parent produces. Is also a bad idea because the event creator shouldn't care who will consume the events later. So only information belonging to the happening event should be in the event.
Executing the DisableCompanyCommand for every company. Only the companies having the matching CityId would change their state. Even though I would do that asynchronously it would produce a huge overhead loading every company on those events. And also for every company getting disabled the same procedure should be repeated to disable all users.
Creating read models mapping ParentIds to ChildIds and loading the childIds according to the parentId in the event. This sounds like the most appropriate solution, but the problem is, how would I know if a new Company is created while I am disabling the existing ones?
I am not satisfied with any of the solutions above. Basically the problem is to determine the affected aggregates for a happened event.
Maybe you have better solutions ?

What you are describing can be resolved by a Saga/Process manager that listen to the CityDisabled event. Then it finds the CompanyIds of all Companies in that City (by using an existing Read model or by maintaining a private state of CityIdsxCompanyIds) and sends each one a DisableCompany command.
The same applies to CompanyDisabled event, regarding the disabling of Employee.
P.S. Disabling a City/Company/Employee seems like CRUD to me, these don't seem terms from a normal ubiquitous language, it's not very DDD-ish but I consider your design as being correct in regard to this question.

Do your requirements mean you have to fire a CompanyDisabled event when disabling a city?
If not - and your requirement is just that a disabled city means all companies are disabled, then what you would do is on your city read model projection you'd listen for CityDisabled events and mark the companies disabled in your read model. (If your requirements are to fire an event for each city then Constantin's answer is good)
Your model is more of a child / parent relationship - its kind of a break in traditional "blue book" thought, but I recommend represent this relationship in your domain with more than a CityId.
In my app something like this would be coded as
public Task Handle(DoSomething command, IHandlerContext ctx)
{
var city = ctx.For<City>().Get(command.CityId);
var company = city.For<Company>().Get(command.CompanyId);
company.DoSomething();
}
public Company : Entity<City>
{
public void DoSomething()
{
// Parent is the City
if(Parent.Disabled)
throw new BusinessException("City is disabled");
Apply<SomethingDone>(x => {
x.CityId = Parent.Id;
x.CompanyId = Id;
...
});
}
}
(Psuedo code is NServiceBus style code and using my library Aggregates.NET)

It's quite probable that you don't have to explicitly force rules like 'enable/disable all related Companies if a City is enabled/disabled' in the domain (write) side at all.
If so, there's no need to disable all Companies when a City is disabled, within the domain. As Charles mentioned in his answer, just introduce a rule that e.g., "a Company is disabled if it is disabled itself (directly) or its City is disabled". The same with Company and its Employees.
This rule should be realized at the read side. A Company in the read model will have 2 properties: the first one is Enabled which is directly mapped from the domain; the second one is EnabledEffective which is calculatable based on the Company's Enabled value and its City's Enabled value. When a CityDisabled event happens, the read model's event handler traverses the City's all Companies in the read model and sets their EnabledEffective property to false; when a CityEnabled event happens, the handler sets the City's every Company's EnabledEffective property back to its own Enabled value. It is EnabledEffective property that you will use in the UI.
The logic can be a bit more complex with CompanyEnabled/CompanyDisabled event handling (in respect to Empoyees) as you must take into account both event info and enabled/disabled status of the host City.
If (effective) enabled/disabled status of a Company/Employee is really needed in the domain side (e.g. affecting the way these aggregates handle their commands), consider taking EnabledEffective value from the read side and passing it along with the command object.

Related

DDD: Can aggregates get other aggregates as parameters?

Assume that I have two aggregates: Vehicles and Drivers, And I have a rule that a vehicle cannot be assigned to a driver if the driver is on vacation.
So, my implementation is:
class Vehicle {
public void assignDriver(driver Driver) {
if (driver.isInVacation()){
throw new Exception();
}
// ....
}
}
Is it ok to pass an aggregate to another one as a parameter? Am I doing anything wrong here?
I'd say your design is perfectly valid and reflects the Ubiquitous Language very well. There's several examples in the Implementing Domain-Driven Design book where an AR is passed as an argument to another AR.
e.g.
Forum#moderatePost: Post is not only provided to Forum, but modified by it.
Group#addUser: User provided, but translated to GroupMember.
If you really want to decouple you could also do something like vehicule.assignDriver(driver.id(), driver.isInVacation()) or introduce some kind of intermediary VO that holds only the necessary state from Driver to make an assignation decision.
However, note that any decision made using external data is considered stale. For instance, what happens if the driver goes in vacation right after it's been assigned to a vehicule?
In such cases you may want to use exception reports (e.g. list all vehicules with an unavailable driver), flag vehicules for a driver re-assignation, etc. Eventual consistency could be done either through batch processing or messaging (event processing).
You could also seek to make the rule strongly-consistent by inverting the relationship, where Driver keeps a set of vehiculeId it drives. Then you could use a DB unique constraint to ensure the same vehicule doesn't have more than 1 driver assigned. You could also violate the rule of modifying only 1 AR per transaction and model the 2-way relationship to protect both invariants in the model.
However, I'd advise you to think of the real world scenario here. I doubt you can prevent a driver from going away. The system must reflect the real world which is probably the book of record for that scenario, meaning the best you can do with strong consistency is probably unassign a driver from all it's vehicules while he's away. In that case, is it really important that vehicules gets unassigned immediately in the same TX or a delay could be acceptable?
In general, an aggregate should keep its own boundaries (to avoid data-load issues and transaction-scoping issues, check this page for example), and therefore only reference another aggregate by identity, e.g. assignDriver(id guid).
That means you would have to query the driver prior to invoking assignDriver, in order to perform validation check:
class MyAppService {
public void execute() {
// Get driver...
if (driver.isInVacation()){
throw new Exception();
}
// Get vehicle...
vehicle.assignDriver(driver.id);
}
}
Suppose you're in a micro-services architecture,
you have a 'Driver Management' service, and an 'Assignation Service' and you're not sharing code between both apart from technical libraries.
You'll naturally have 2 classes for 'Driver',
An aggregate in 'Driver Management' which will hold the operations to manage the state of a driver.
And a value object in the 'Assignation Service' which will only contain the relevant information for assignation.
This separation is harder to see/achieve when you're in a monolithic codebase
I also agree with #plalx, there's more to it for the enforcement of the rule, not only a check on creation, for which you could implement on of the solutions he suggested.
I encourage you to think in events, what happens when:
a driver has scheduled vacation
when he's back from vacation
if he changes he vacation dates
Did you explore creating an Aggregate for Assignation?

DDD Relate Aggregates in a long process running

I am working on a project in which we define two aggregates: "Project" and "Task". The Project, in addition to other attributes, has the points attribute. These points are distributed to the tasks as they are defined by users. In a use case, the user assigns points for some task, but the project must have these points available.
We currently model this as follows:
“task.RequestPoints(points)“, this method will create an aggregate PointsAssignment with attributes points and taskId, which in its constructor issues a PointsAssignmentRequested domain event.
The handler of the event issued will fetch the project related to the task and the aggregate PointsAssigment and call the method “project.assignPoints(pointsAssigment, service)”, that is, it will pass PointAssignment aggregate as a parameter and a service to calculate the difference between the current points of the task and the desired points.
If points are available, the project will modify its points attribute and issue a “ProjectPointsAssigned” domain event that will contain the pointsAssignmentId attribute (in addition to others)
The handler of this last event will fetch the PointsAssingment and confirm “pointsAssigment.Confirm ()”, this aggregate will issue a PointsAssigmentConfirmed domain event
The handler for this last event will bring up the associated task and call “task.AssignPoints (pointsAssignment.points)”
My question is: is it correct to pass in step 2 the aggregate PointsAssignment in the project method? That was the only way I found to be able to relate the aggregates.
Note: We have created the PointsAssignment aggregate so that in case of failure I could save the error “pointsAssignment.Reject(reasonText)” and display it to the user, since I am using eventual consistency (1 aggregate per transaction).
We think about use a Process Manager (PointsAssingmentProcess), but the same way we need the third aggregate PointsAssingment to correlate this process.
I would do it a little bit differently (it doesn´t mean more correct).
Your project doesn´t need to know anything about the PointsAssignment.
If your project is the one that has the available points for use, it can have simple methods of removing or adding points.
RemovePointsCommand -> project->removePoints(points)
AddPointsCommand -> project->addPoints(points)
Then, you would have an eventHandler that would react to the PointsAssignmentRequested (i imagine this guy has the id of the project and the number of points and maybe a status field from what you said)
This eventHandler would only do:
on(PointsAssignmentRequested) -> dispatch command (RemovePointsCommand)
// Note that, in here it would be wise to the client to send an ID for this operation, so it can do it asynchronously.
That command can either success or fail, and both of them can dispatch events:
RemovePointsSucceeded
RemovePointsFailed
// Remember that you have a correlation id from earlier persisted
Then, you would have a final eventHandler that would do:
on(RemovePointsSucceeded) -> PointsAssignment.succeed() //
Dispatches PointsAssignmentSuceeded
on(PointsAssignmentSuceeded) -> task.AssignPoints
(pointsAssignment.points)
On the fail side
on(RemovePointsFailed) -> PointsAssignment.fail() // Dispatches PointsAssignmentFailed
This way you dont have to mix aggregates together, all they know are each others id´s and they can work without knowing anything about the schema of other aggregates, avoiding undesired coupling.
I see the semantics of the this problem exactly as a bank transfer.
You have the bank account (project)
You have money in this bank account(points)
You are transferring money through a transfer process (pointsAssignment)
You are transferring money to an account (task)
The bank account only should have minimal operations, of withdrawing and depositing, it does not need to know anything about the transfer process.
The transfer process need to know from which bank it is withdrawing from and to which account it is depositing to.
I imagine your PointsAssignment being like
{
"projectId":"X",
"taskId":"Y",
"points" : 10,
"status" : ["issued", "succeeded", "failed"]
}

How to enforce invarients in aggregate relationships

I am new to event sourcing and ddd and trying to create a simple app to learn more, but I'm strruggling with how to model a relationship between two aggregates.
The idea is to allow companies to create activities that can then be searched for by users.
I want to be able to enforce the rule that a company can only have so many active activities depending on thier membership level.
My first approach would be to have the Company be the aggregate root which would contain the list of Activities and easily control this. However, this means I would have to go through the Comapny Aggregate to access every Activity, which hisn't ideal as most actions against an activity does not depend on the Company.
My second approach was to have seperate Company and Activity aggreagtes. This means that I would have to first raise a ActivityCreated event, then an ActivityAddedToCompany event which would throw an exception if the company is already full of Activities. This approach seems better but I'm not sure if needing the ActivityAddedToCompany is a flag that I have not seperated the aggregates correctly as in a happy path, the ActivityCreated and ActivityAddedToCompany would always be stored after each other.
Is the second approach better or am I missing something basic in Domain Driven Design?
As per your clarifications:
an Activity does not have to be created by a Company
This suggests that Activity should be an aggregate of its own. It has a lifetime separate from any other aggregate.
An Activity can only be registered to one Company
The Activity would have a reference back to the Company via an ID. Effectively, a foreign key. When it is assigned to a Company, it raises an event indicating that the assignment was made.
a Company can only have 5 Activities at any one time
If you were using a standard RDBMS system to manage these rules, you would have a transaction that checks the number of Activities and either approves or rejects the addition of a new Activity. Similarly, in your domain, you can model this through a two-phase commit.
When you assign an Activity to a Company (AssignToCompany command), you raise an AssignedToCompany event. A ProcessManager (PM) will receive that event and send a command to Company (AssignToActivity) and the Company can either accept (AssignedToActivity) or reject that based on the count (RejectedAssignToActivity).
If the latter, the PM will receive the RejectedAssignToActivity event and send a command back to Activity to remove the company (UnassignCompany) which will raise the CompanyUnassigned event.
Optional:
The PM will receive the CompanyUnassigned event and send an UnassignFromActivity command to the Company. This way, you can unassign an activity if needed and have the Company be aware of the change.

How are consistency violations handled in event sourcing?

First of all, let me state that I am new to Command Query Responsibility Segregation and Event Sourcing (Message-Drive Architecture), but I'm already seeing some significant design benefits. However, there are still a few issues on which I'm unclear.
Say I have a Customer class (an aggregate root) that contains a property called postalAddress (an instance of the Address class, which is a value object). I also have an Order class (another aggregate root) that contains (among OrderItem objects and other things) a property called deliveryAddress (also an instance of the Address class) and a string property called status.
The customer places an order by issueing a PlaceOrder command, which triggers the OrderReceived event. At this point in time, the status of the order is "RECEIVED". When the order is shipped, someone in the warehouse issues an ShipOrder command, which triggers the OrderShipped event. At this point in time, the status of the order is "SHIPPED".
One of the business rules is that if a Customer updates their postalAddress before an order is shipped (i.e., while the status is still "RECEIVED"), the deliveryAddress of the Order object should also be updated. If the status of the Order were already "SHIPPED", the deliveryAddress would not be updated.
Question 1. Is the best place to put this "conditionally cascading address update" in a Saga (a.k.a., Process Manager)? I assume so, given that it is translating an event ("The customer just updated their postal address...") to a command ("... so update the delivery address of order 123").
Question 2. If a Saga is the right tool for the job, how does it identify the orders that belong to the user, given that an aggregate can only be retrieved by it's unique ID (in my case a UUID)?
Continuing on, given that each aggregate represents a transactional boundary, if the system were to crash after the Customer's postalAddress was updated (the CustomerAddressUpdated event being persisted to the event store) but before the OrderDeliveryAddressUpdated could be updated (i.e., between the two transactions), then the system is left in an inconsistent state.
Question 3. How are such "violations" of consistency rules detected and rectified?
In most instances the delivery address of an order should be independent of any other data change as a customer may want he order sent to an arbitrary address. That being said, I'll give my 2c on how you could approach this:
Is the best place to handle this in a process manager?
Yes. You should have an OrderProcess.
How would one get hold of the correct OrderProcess instance given that it can only be retrieve by aggregate id?
There is nothing preventing one from adding any additional lookup mechanism that associates data to an aggregate id. In my experimental, going-live-soon, mechanism called shuttle-recall I have a IKeyStore mechanism that associates any arbitrary key to an AR Id. So you would be able to associate something like [order-process]:customerId=CID-123; as a key to some aggregate.
How are such "violations" of consistency rules detected and rectified?
In most cases they could be handled out-of-band, if possible. Should I order something from Amazon and I attempt to change my address after the order has shipped the order is still going to the original address. If your case of linking the customer postal address to the active order address you could notify the customer that n number of orders have had their addresses updated but that a recent order (within some tolerance) has not.
As for the system going down before processing you should have some guaranteed delivery mechanism to handle this. I do not regard these domain event in the same way I regard system events in a messaging infrastructure such as a service bus.
Just some thoughts :)

How to model the requirement using domain driven design

I have a requirement where i need to group the two events as one transaction by grouping them on certain criteria. Below is the some thoughts on the requirement.
Event ::
We will receive events continuously to our systems.
Each event will have some buffer time to group with other event.
If buffer time elapses then we need to discard the event.
We need to group the two events into one group depending on the two events information.
If event information is not sufficient then we will send event info to other component which will response with corrected data.
Whenever we grouping the events some times we want to hold the other event if related event went to data correcting component even though we are not 100% sure about the matching criteria. This step we want to perform because we want to match the events as many as possible.
I want to model this requirement using domain driven design any suggestions will be appreciated.
Without knowing your business requirements, it's kind of hard to answer. But we can start with assumptions and definitions first:
I refer to an event in DDD as something that is important for your domain, has happened (in the past), is a undeniable fact and cannot be undone.
In my definition either aggregates or domain services are responsible for emitting events.
So your group of events looks like a concept that says that a group of related events is something important to my domain, too.
I guess you can go two ways to think about that concept:
A group is a special view on your already happened events. Then a group is just a component which state is derived from a list of related events.
A group is an aggregate that is a kind of a process that has a life cycle and based on state emits a single group event when the criteria for finishing a group is met
In the first case you can implement a group query that listens to published events and projects them to your group concept
In the second case you have an aggregate that reacts to business requests (you can call this a command) and manages some persistent state. When you request your aggregate to create a group and your aggregate is in the right state to do this, then your aggregate emits a group event.

Resources