A
A
alexg-nn2019-09-23 13:17:34
Problem-Based Design
alexg-nn, 2019-09-23 13:17:34

How to implement delayed events?

Hey!
I'm trying to beautifully implement the mechanism of deferred events in an architecture with a DDD approach. By deferred, I mean those events that are not initiated directly by user commands, but must occur later. As an example: there is a site where the user aggregate has a date of birth. We want to congratulate him on this day by sending a letter. In addition, in the limited context of the store, this user must have bonuses credited to the account. The starting point of the algorithm is the moment when the user indicates the date of birth in the profile.
Reflecting on the task, I came to the conclusion that it is better to move work with time into a separate Scheduler context, which will twitch the crown from the outside. There are several options for how this scheduler interacts with other contexts.
1. At the moment when the user specifies the date of birth, we plan specific commands, further pseudocode

Scheduler->schedule(new SendHappyBirthdayEmail($email), $birthdate);
Scheduler->schedule(new IncreaseBonuses($user, $amount), $birthdate);

When $birthdate arrives, the scheduler will execute the commands.
What pros and cons I see in such an implementation:
+ quite obvious and simple
- the scheduler knows a lot about the outside world
- the composition of the teams can easily change during the time until the event has occurred. Let's say instead of an email, we have now decided to send a paper postcard. It turns out that we need to remove the planned commands for sending emails and add new commands for delivering postcards.
- during the execution of the command, an additional context may be required that cannot be stuffed into the command parameters. For example, it is necessary to take into account the status of the buyer before sending a postcard. And the status can change at any time and is certainly unknown at the time of planning the team.
- there is a need to delete unnecessary events, for example, if the date of birth has changed (a typo during registration, for example)
- as for me, commands are the application level, while Scheduler is the domain level. It turns out that the domain level knows about the application, which is wrong.
2. The Scheduler simply sends one event with some necessary frequency, for example, TimeHasChanged. The rest of the contexts listen to this event and decide how to react to it.
Pros and cons:
+ the scheduler does not know anything about how they react to dates
+ it is easy to adapt to changes in the logic of the reaction to the event, because it (the reaction) occurs exactly at the moment of the event, rather than at the moment of its planning.
+ no need to delete incorrectly scheduled events
- contexts subscribed to this event do not understand how to react to it. For example, the user context needs to go to the repository every time and see if anyone has a birthday on that day. And if some context is waiting for the onset of many dates, then the search for the right one becomes too expensive.
- contexts know too much about dates, because they themselves operate with them.
3. Scheduler is used as an "alarm clock"
$userId = 'j123jjkh3j2jh3j2h';
$key = 'user_birthdate:' : $userId;;
Scheduler->schedule($key, $birthdate);

At the time of the date, it sends out a TimeHasCome() event containing the same $key that was given to it. That is, the rest of the contexts simply ask him to "remind me when this date is."
+ all the same as in item 2, plus the context does not need to bother with searching by date, it can easily search by the key fragment, in my example by $userId, extracting it from $key.
+ contexts do not operate with dates, shifting it to the scheduler. Instead, they are waiting for the event that they themselves have planned.
- incorrect events also need to be deleted if they are not needed, otherwise false positives will occur. But, here you can overcome this by deleting by the key mask or by the whole key $key.
Here are the solutions that came to mind. If you have any ideas or comments on this issue, please share.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question