Search code examples
entity-frameworkarchitecturetransactionsdomain-driven-designddd-repositories

Create multiple aggregates in one transaction


My bounded context(inventory) receives an event with quantity 5. Where 5 is the number of pallets were unloaded from the truck in the warehouse. And now in my inventory BC I want to create 5 aggregates (foreach pallet 1 aggregate). How can I do that in my application layer? What if I succeed to create only 3 of them? I can't create them transitionally, cause my persistent storage is file based. What should I do?


Solution

  • You should probably treat the recording of the receipt event and generation of the five pallets as two separate transactions.

    The changes are across two aggregates in your case, but your application service should ideally deal with one single aggregate, as much as possible. Domain Events are the right structures to solve such problems of extended transactions, be it between aggregates in a single BC, or across BCs.

    So your application service would record the receipt of five pallets as a transaction, and bubble up a domain event (say PalletsUnloaded) with sufficient context and data. The event would be passed on as a data structure to a message broker, to be retrieved by subscribers registered for the domain event.

    The Pallet aggregate would then catch the event through an event-specific subscriber and process it, in one of two ways:

    1. You can create the five pallets in one single pass. Transaction-wise, this approach is a bit risky because if you are using files as persistent storage, there may be failures and you may not have granular data to identify the exact issue
    2. You catch the event and create five separate event messages (say CreatePallet), each of which is submitted back to the message broker. A subscriber for this event would pick them up and create pallet records one by one. You will accurately know which one failed and why

    The 2nd approach is also safer because if you use reliable message brokers like RabbitMQ as the transfer mechanism for events, you can send the errored event into a dead-letter queue or set up mechanisms to retry the processing later. You can also build a separate error-handling process/view that deals with, and processes, errored events.