As is the case with most applications, it depends on what you’re trying to achieve which angle makes sense. The answer’s going to be rather large, but I feel it’s required to provide the necessary background. So, here goes.
The process of publishing an event and handling an event are, in most scenarios, separated from one another.
More specifically put, Axon uses the
EventStore interfaces for publication and storage. Note that from Axon’s point of view, the
EventStore is nothing more than a specific implementation of the
EventBus which adds the option to append events to the store.
When it comes to handling events, Axon uses so-called Event Processors. The
EventProcessor has a couple of implementations, which differ with how they receive their events. Firstly, there’s the
SubscribingEventProcessor (SEP for short) uses a
SubscribableMessageSource to receive its events from. It is the
EventBus that implements the
SubscribableMessageSource, which makes it the default source for a SEP’s events. Furthermore, these events are provided in the same transaction as they’re published. That means that if event handling supported through a SEP fails, the event publication would essentially be rolled back. Simply put, the SEP uses an event-push mechanism.
The other type of Event Processor is the so-called
StreamingEventProcessor. At this time, the
StreamingEventProcessor has two implementations, (1) the
TrackingEventProcessor (TEP) and (2) the
PooledStreamingEventProcessor (PSEP). The
StreamingEventProcessor implementations use a different message source since they’re required to stream the events. This is the so-called
StreamableMessageSource. Furthermore, it is the
EventStore which is an implementation of the
StreamableMessageSource, as it can provide an application with the capability to start at any position in the stream/store. Lastly, the
StreamingEventProcessor retrieves events on its own in separate threads and thus separate transaction. Simply put, a Streaming processor uses an event-pull mechanism.
Now, with that piece of background, I feel there is some common grounds to move to the Saga.
The Saga is in essence a specialized type of an Event Handling Component. In Axon, Event Handling Components receive events by the Event Processor. So, it is the Event Processor that invokes the
@SagaEventHandler annotated methods that you would construct in your application using Axon.
If you would require “event saving to event store and event firing and event execution” to be part of the same transaction, your only option would be to use a SEP as the processor for your Saga. Doable, with some configuration, but in essence not the recommended usage of a Saga. Axon defaults Event Processors to the
TrackingEventProcessor, as this approach separates your transactions. In essence, it encourages your application to work in an uncoupled fashion from one another, which is most definitely the strong suit of using a Message Driven Architecture as supported through the framework.
Instead of trying to make sure that event publication, storage and handling are a single transaction, we recommend that storage and handling are separated from one another. Essentially the fact the event was stored is the bread and butter of an Event Sourced system. Furthermore, if something isn’t happy with the event (e.g. event execution fails), that’s of no concern of the event publisher.
The decision leading to the fact/event has been made, whatever some other process thinks of this does not influence the original decision making process.
Now, to circle back to whether Axon supports either Orchestration or Choreography, I’d state that you can achieve both with Axon. You could have a Saga that orchestrates the entirety of your complex business transaction, or you create several Saga’s which choreograph with one another to achieve the same goal. As far as I was concerned, the specifics about transactions spanning event publication/handling didn’t play into this part to be honest, although I might have misunderstood things.
What using a Saga would mean in your application, is that you have a component that reacts to facts (events) and tries to perform an action (command, 3rd party operation) based on it. If the action fails, it is the Saga that needs to deal with this by performing a compensating action, if necessary.
Hoping this sheds some light on the Saga’s place inside an Axon application, @isuru.