I'm modelling a scheduling application and wonder how it could be avoided to update multiple aggregate roots (AR) in one transaction. I understand the fundamental problem of changing multiple ARs in one transaction, since it could cause a lot of conflicts. However, I don't see an alternative in my case.
My current approach is that each task (T-1 ... T-6) is an aggregate root instance. Each tasks has a
endTime (can not be derived from
dependentTasks. Furthermore each
Resource is an aggregate root, as well. It contains a profile with times where the resource is available.
The following invariants apply:
- Tasks on a single resource must not overlap each other.
- Dependent tasks can only be scheduled after the planned end of the predecessor.
- Tasks are prolonged if there resource is not available for a certain time ("break").
Let's say I want to move T-1, then
- T-2 must be moved to avoid overlapping on Resource A
- T-3, T-4 must be moved, because both can only start after T-1 is finished
- T-5 must be moved to avoid overlapping on Resource C
- T-6 must be moved, because it can only start after T-5 is finished, which in turn was already moved
So, a single move in the schedule (T-1) leads to changes in all other tasks! In the (good!) book "Implementing Domain-Driven Design" the generic answer is "use eventual consistency", but I think that wouldn't solve the problem, since moving tasks around is basically a transaction. I don't want a state where half of the tasks are already moved and the other half is in the old state because of a conflict.
In practice it gets even worse, because the schedule could be edited by multiple concurrent user, but maybe that is a story for another time.
Is there a way to avoid modification of multiple task instances in one transaction? Or, is there at least way to reduce the number of modifications / conflicts?