Services that are responsible for monitoring the balance and performing certain actions when it drops below zero.
Summary: The way this is handled in source systems is not really all that different from the alternatives.
Speeding up the second - the advantage of having a domain model is to ensure that all proposed changes are consistent with business rules. CQRS borrowing: we send command messages to the command handler. The handler loads the state of the model and tries to apply the command. If the command is enabled, state changes to the domain model are updated and saved.
After saving the state of the model, the command handler can request this state to determine if their outstanding actions are. Udi Dahan details this in his conversation Reliable Messages .
Thus, the easiest way to describe your service is the one that updates the model each time the account balance changes and sets the flag “over the account” if the balance is negative. After saving the model, we plan any actions related to this state.
Part of the rationale for the source of events is that the state of the domain model is derived from history. That is, when we try to determine whether the model allows us to use the command, we load the history and calculate the current state from the history, and then use this state to determine whether the command is allowed.
In practice, this means that we can write the AccountOverdrawn event at the same time as we write the AccountDebited event.
This AccountDebited event can be subscribed to - Pub / Sub. Typical processing is that new events are published after they are successfully written to the record book. An event listener who subscribes to events leaving the domain model observes the event and schedules the execution of the command.
Digression: usually we need to perform at least a single execution of these actions. This means tracking confirmation.
Therefore, an event handler is also a stateful thing. There is no business condition in it, and, of course, there are no rules that would allow it to reject events. What he tracks, what events he saw, and what actions need to be planned. The rules for loading this event handler (often referred to as the process manager) are similar to the rules of the domain model - they load events from the record book to get the current state, and then see if any event is being processed.
Thus, it really subscribes to two events - the AccountDebited event and any event is returned from the operation to confirm that it has completed.
The same mechanic can be used to update the domain model in response to events from other sources.
Example: suppose we get the FundsWithdrawn event from an ATM, and we need to update the account history to match it. Thus, our event handler loads, updates itself, and assigns the RecordATMWithdrawal command to run. When the team loads, it loads the account, updates balances and records the events AccountCredited and AccountOverdrawn, as before. The event handler sees these events, loads the correct state of the process state based on metadata, and updates the state of the process.
In CQRS terms, all this happens in “recording models”; these processes are related to updating the record book.
The balance request itself is simple - we have already shown that the balance can be obtained from the history of the domain model, and exactly how your balance is expected to work.
Summarizing; at any time, you can download the history of the domain model, request its status, and you can download the history of the event processor to determine which work still needs to be confirmed.