Commands that create events in the future

Hi!

I’ve got a conceptual question: We have a business case, where a lets say

‘closeInboxCommand’

should create an event ‘inboxClosedEvent’. But that event should have an effect after 17 o’clock only.
I would suggest that the event could get a timestamp-field ‘onlyValidAfter’, and when constructing the aggregate,
the event is only taken into account if ‘currentTime > onlyValidAfter’.

That should work fine, unless we are using snapshots. If I create the snapshot before 17 o’clock, the
inboxClosedEvent will never have any effect.

Has Axon any concepts to deal with such a business case?

cu,
Dirk

Hi Dirk,

It seems like you want to introduce some form of ‘dead line’ in your aggregate.

We are working on an approach to have a nicer dead line API then currently present in the framework.

Till then though, probably the EventScheduler might solve this issue for you.

Using the EventScheduler however means it will not be a domain event message, but a regular event message.

Thus, from the EventStore it’s point of view, it is not tied to any aggregate, hence can not be part of a replay.

If the ‘InboxClosedEvent’ you’re referring too has to be a Domain event, the following pops up to mind (not sure if this is the cleanest approach in your situation though):
Have a Saga tied to that aggregate, which triggered on certain events arrives at a state that it knows “eventually I want to close an inbox”.
When it reaches that state, it can thus use the EventScheduler to schedule the knowledge that “you want to close an inbox at 1700”.
The event you schedule can then be handled by that exact same saga instance, which open handling that events knows 'ah, I need to publish a ‘CloseInboxCommand’.

Any how, that’s what popped up to mind right now. You probably know better whether that works in your (example) application or not.

Hope this helps!

Cheers,
Steven

Hi Steven,

thanks for your help! I would definitely have a look a EventScheduler and Sagas. Think that will work. I will try to go with real domain events.
But that seems to be something that can’t be easily solved right now.

I’m wondering how we could solve the same if we would have events that have to sort into the event stream in the past.
That would even not be possible with the Sagas, right?

Speaking in general, we sometimes need to have bitemporal historization. So events can occur that should be applied in the future or in the past.
Would be great if axon could offer a general solution for it.

I could image something like an ‘applyEventAt’ date. But I understand that this makes it hard to create the aggregate,
since snapshotting isn’t possible in that case anymore.

cu,
Dirk

Hi Dirk,

Glad to have been of help here!

If you end up with any follow up question, I’d be happy to help.

You’re making the right assumption that Axon currently does not support bitemporal historization, although I do believe it would be an awesome feature to have.

Not sure how frequent the use cases would be though, so also uncertain how pressing such a feature would be.

Thanks for sharing though, I’ll discuss this with Allard somewhere soon.

Interested to see his point of view on it.

Cheers,

Steven

Hi Dirk,

we have a number of clients that already to bitemporal querying based on the current implementation. Essentially, one of the times is fixed in the events store: it is the time when you know something. The other time aspect is when it actually happened. For example: I now know that someone will move to another address in 2 months time.
This allows you to answer queries like “In july, what did I think his address would be on the first of august?”

Personally, I have some difficulty understanding why this would mean events are scheduled in the future. If someone want to close the inbox, and this should only have an effect some hours later, than the time at which it will take effect is part of the state of an aggregate. The actual indication to close the inbox is a state change, the “refusing to take action on a closed inbox” is just a behavior change based on the state that was set earlier.

In short, my take in this is that events happen in present time, and they should model time as part of them. So instead of scheduling events, handlers of the event should schedule a task to start cleaning up at a certain time.

Cheers,

Allard

I did a similar thing using a Aggregate/Saga pair, but juts a little more verbose, something like:

closeInboxCommand

inboxCloseScheduled

Saga schedules the action to be taken and after execution send another command to the Aggregate

confirmInboxClosed

inboxClosedEvent

or something else in case of failure. So in your event store you end up with 2 events instead of one…

inboxCloseScheduled
inboxClosedEvent

In more complex cases this can turn to be TOO verbose, but that’s the way it is… :slight_smile:

Thanks for all your input! Antonios solution would be the implementation of what Allard proposed, right?

That sounds like a clean implementation of the reality to me. But that all stops working, if you have events that have an effect on the aggregate state
in the past. E.g. you can buy an insurance in february, that protects you for the whole year. So starting in january. This could be cheaper than getting an insurance for a couple of months only.

So the state of the aggregate would be different in december last year than in january this year.
And you couldn’t schedule a command for it, since it already happend in the past.

I would think that this could be implemented by applying all events depending on a second timestamp “eventIsValidAfter”.
So you could ask something like: How does my aggregate insurance state look like in december last year. And what was the state in january.

But to achieve this, axon couldn’t use snapshots anymore and you would have to call the eventhandlers for all events all the time, depending on the requested validity timestamp.
Wouldn’t be performing very well, but would easily implement real bitemporal historization. Even for events that get valid in the past.

But maybe the use case is just an edge case that no one else has.

Hi,

yes, an Aggregate/Saga pair may help here. However, another solution is to make your models time-aware.

Let’s say that today, you receive a notification that my address changed 2 weeks ago. The event is inserted with today’s timestamp, as the registration happened today. However, the “as-of” date of the change is 2 weeks ago. Now, if I want to know: what was my address last week, it should give me the new (correct) address. However, if the questions is: what did I think my address was last week, seen from what we knew yesterday, it would still be the old (incorrect, as we know now) address.

Basically, it means the entries in your model will have some record of validity. If you want to know your point of view at a certain date, simply “replay” events up to that date, and check the model for the item with the correct validity.

Sagas are very useful when it comes to planning ahead. For example, I register the fact that I will have a new address in 2 weeks time. That event takes place now (don’t schedule this!!), but the as-of date is two weeks from now. In certain cases, it may be desired to get a notification that a planned change has actually occurred. This is where a Saga could do some work: keep track of the next upcoming change and scheduling an event for that. This type of event doesn’t actually need to change any aggregate state. In the end, nothing changed in the system. It’s merely a “reminder” of a change already made some time in the past.

Hope this helps.
Cheers,

Allard