Should deadlines be scheduled in a @CommandHandler or @EventSourcingHandler?

Should deadlines be scheduled in a @CommandHandler or @EventSourcingHandler?

For an aggregate:

  • When scheduling a deadline the deadlineManager.schedule(..) method returns a String deadlineId.
  • Given that we need to store that ID in the state of the aggregate (in case we need to cancel the deadline later) I assumed it would go in an @EventSourcingHandler (since we are changing the state of the aggregate).
  • However, placing it in an @EventSourcingHandler results in tests failing with: deadlineId has different value when sourcing events.
  • I believe this is expected behaviour because the test fixture runs the ā€˜given, when, thenā€™ which is defined on it and then runs each event sourcing handler again and makes sure that the states match.
  • Since when the @EventSourcingHandler is run for the second time the scehdule(...) method is called again and a different deadlineId is stored as the state - this results in conflicting state between the first time the handlers are run and the second.
  • When using a @CommandHandler the test fails as well.

So my question is: what is the correct way to schedule a deadline and store the deadlineId for an aggregate?

For a saga:

  • Iā€™m assuming it is best practice to schedule a deadline on a @SagaEventHandler. Everything works here without issue.

The short answer is, in command handler.

String schedule(Instant triggerDateTime, String deadlineName, Object messageOrPayload)

The result of this method is a deadlineId which you can include in the event that you will publish/apply in this same command handler, I presume. The event sourcing handler will eventually update the state of your aggregate and there you can store the deadlineId as an attribute as well.

Some other commands might result in canceling this particular deadline (you already have it in the aggregate state).

If the deadline expires (before it was canceled), the deadline will kick in:

@DeadlineHandler(deadlineName = MY_NAME)
void on(YourMessageOrPayloadType payload)

This deadline handler can be treated as a command handler, the diference is that the message is not a command but a deadline expiration message. This deadline handler can publish/apply event.

Best,
Ivan

2 Likes

Thanks Ivan - that makes a lot of sense.

Another related question. If we set a deadline, say for 15 mins, but 10 mins later we mark an aggregate as deleted - will the deadline still be triggered after 5 more mins?

Is it best practice to manually cancel deadlines in the command handler of the command which eventually causes the aggregate to be marked as deleted? Or should we not worry about that case?

1 Like

I believe that you have to (manually) cancel that deadline in the command handler. Most probably, it does not make much sense to have that deadline expires after you marked the aggregate deleted. Nevertheless, the deadline handler method will not be able to publish/apply any (domain) event for the aggregate that is marked as deleted.

1 Like

Hi,
Quite old thread but documentation does not mention some logic.
Would it be possible to add where should the deadline be scheduled and deadline id stored (event) in the reference guide?
Also can we cancel the deadline the EventSourcingHandler of the aggregate? ā†’ would it not be better in the event handler?
If in the command handler, we are not sure that the event will be successful published but deadline already unscheduled

If in the command handler, we are not sure that the event will be successful published but deadline already unscheduled

I guess phrasing this in another way the question becomes, in following scenario:

  1. schedule() is called within the body of a @CommandHandler and you receive a String deadline ID back.
  2. Somewhere within the rest of the @CommandHandler an exception is thrown and the unit of work needs to be rolled back.

Then is the deadline that has been scheduled also rolled back?

I think the answer is noā€¦ but I have not tested it.

Thanks for your feedback @Yoann_CAPLAIN

We are aware the reference guide needs some love. Updating it is on the road map, but currently, the focus is on AxonIQ Academy. That is because we can explain such things in more detail there.

For example, the ā€œImplementing Deadlines in Aggregates and Sagasā€ lesson in Designing complex processes with Axon course tries hard to answer the above question. I canā€™t simply copy it here as it is five chapters describing different scenarios and various components.

That is also why itā€™s not that easy to add a synthesized version of it to the reference guide. But that is the plan. Once we have the complete deep dive in Axon ready, weā€™ll be updating the reference guide accordingly.