Command vs Event scheduling

Hi,

I’m wondering if it wouldn’t be much better to schedule commands instead of events in Axon. Mainly for these two reasons:

First of all, scheduling commands would conceptually make more sense. An event informs listeners that something happened/changed in the application. However, scheduled events in Axon are generally used to affect change. Often a saga will listen for the event and dispatch a command. So most scheduled events today are already effectively used as commands anyway.

Secondly, scheduling commands instead of events could make the majority of sagas obsolete. Sagas are a necessary evil and will always serve as the ‘glue’ between different aggregates, but if we don’t need to involve sagas in scheduling anymore it would be a big win. In my own application 75% (12 out of 16) of my sagas are only involved in the scheduling of events followed by a dispatch of commands. If we schedule commands we could leave it up to e.g. the aggregate to do so without any serious drawbacks.

To make this more than a theoretical discussion I’ve built a proof-of-concept CommandScheduler that uses Quartz for scheduling and the Axon (XStream) serializer to serialize the commands. I also built and tested a basic example aggregate (not using event sourcing) that models a notification to users and uses the CommandScheduler. Attached are a bunch of source files:

  • The interface and implementation of the CommandScheduler
  • The basic example aggregate that uses the CommandScheduler
  • Plus some classes that make it easy for command handlers to retrieve the ScheduleToken (if any) involved in the dispatching of the command
    I would love to get your input.

Thanks,
Rene

CommandScheduleToken.java (1.94 KB)

DispatchCommandJob.java (3.21 KB)

QuartzCommandScheduler.java (7.11 KB)

QuartzCommandSchedulerFactoryBean.java (3.57 KB)

ScheduleTokenParameterResolverFactory.java (1.66 KB)

CommandScheduler.java (1.56 KB)

Notification.java (4.19 KB)

Hi Rene,

it sounds like a good idea. I hadn’t though about scheduling commands yet, but realize that it may simplify things a lot. I recognize the pattern where Sagas react on a “DeadlineExpiredEvent” and then unconditionally send out a command based on that event.

However, scheduling commands from an Aggregate does sounds a bit “iffy”. In you sample, it’s an Aggregate that schedules a command for itself. That’s just something to get used to, I guess. But once aggregates start sending commands to eachother (as far as you can say that, as the commands aren’t tightly couples from an API point of view), it may start getting complicated. The idea of Sagas versus Aggregates is that Sagas are about process, and aggregates about single steps in that process.

Just out of curiousity, what use case do you see to have the ScheduleToken injected as a parameter in the command handler? Since the command is being handled, I expect the job the token is referring to, has been expired. Cancelling it wouldn’t make more sense. Or am I overlooking something?

Cheers,

Allard

Hey Allard,

Thanks for looking into this. I agree that having the aggregate schedule commands sounds a bit iffy at first, but like you say I think it’s more a matter of unfamiliarity. You could argue that the aggregate is still carrying out its single step directive, i.e. it gets a command to do A and part of A is scheduling a command for the future (as is validation of the command and publishing one or more events). You could even argue that not scheduling the command is a breach of contract by the aggregate: isn’t the aggregate the sole command handler, i.e. in charge of making sure the command is executed in full?

I agree with you that it becomes ugly when the aggregate starts to issue commands for other components of the system, but even that may not be fundamentally bad. The aggregate is the sole handler for that command so again you could argue that it’s the responsibility of the aggregate to make sure the command is executed even if that includes dispatching spin-off commands (to other components), but now we’re on thin ice.

In terms of implementation, it would be nicest if aggregates provide an easy way to schedule a command, i.e. not using an injected CommandScheduler, but using an instance method comparable to apply() for events. This way, unit tests would be easier I imagine because there could be a simple fixture method to check if a command was scheduled.

Finally, to come back to your last question regarding injection of the schedule token, I think there is a use case when a command may come from the scheduler but may also come via another way, for instance if the user presses a button. If the user presses the button before the schedule expires, it is often necessary to cancel the command schedule, however that’s only necessary if the token is different than the stored token. In other words, if you cannot provide a way for the aggregate to check if the tokens are equal you always need to cancel the command schedule to be on the safe side (which feels bad because it would be unnecessary in 90% of the cases). In the example aggregate I posted you don’t need this hocus-pocus because commands are validated anyway from the aggregate state, but that’s not possible for every aggregate.

Hope that last paragraph made any sense ;).

Rene

Hi guys,

After reading this discussion, I start getting Allard’s idea why there is no commands scheduling through an aggregate. However, it would be nice, indeed, for a Saga, to be able to react to an event by just issuing a command, especially if you, like me, have the use case where a Saga deals more or less with the events of a single aggregate. On another note, I can achieve everything I want with the current state of the framework, without using command scheduling, only bad thing I actually have to think about it and do some boilerplate tasks beforehand.

In recent future, I’d look at the proposed CommandScheduler interface that Rene proposed, and might “borrow” it for myself, if it is going to save me a lot of work in the future. If this gets into axon build, probably, am going to use it only in Sagas, not in aggregates themselves, as I think with the current paradigm I have in mind, it is going to violate some conventions if I were to use it directly in aggregates.

I also made a small project to showcase how such a Saga can be used:

https://github.com/lc-nyovchev/axon-simple

As you can see in this code:

https://github.com/lc-nyovchev/axon-simple/blob/master/src/main/java/org/athend/axon/simple/domain/UserLockSaga.java

We schedule a superfluous event which is not handled anywhere but in the same Saga so we can go through the normal command->event flow. I realize that this is a very narrow usage of a Saga but a viable one nonetheless. If we had the possibility for command sourcing, code would have looked a bit cleaner.

Kind regards,

Nikola