Associate saga with aggregateIdentifier

Hi there, I may have misread the documentation, but something puzzles me:

I have a financial transaction, which in certain cases needs some post processing. The post processing needed is fairly simple: It’s a matter of calling a few commands on the transaction aggregate. Depending on the outcome of the commands, events are raised accordingly. To me sagas seem like the obvious solution.

A saga is created upon creation of the transaction aggregate (An event is raised containing the aggregate identifier). So far so good. Now, I realize that I can create a unique identifier for each post processing task, and associate it with the saga. However, this seems a bit like overkill, since the post processing does not operate across aggregates.

Is it possible somehow, to simply associate a saga with the aggregate identifier once, and then subscribe to which ever aggregate event I choose in the saga (Much like the eventlisteners on the aggregate)?

Yes, I could do this by explicitly putting the aggregate identifier on each relevant event, and set is as associationProperty on each listener in the saga, but it seems kind of redundant to raise events containing the aggregate identifier from within the aggregate it self :slight_smile:

Hi Jeppe,

I am assuming you use Axon 1.4.

If I understand your use case correctly, I am not sure a Saga is the best solution in this case. You saga responds to events from a “transaction” and, as a reaction, sends commands to that same (?) transaction. If that is the case, why not do the post processing immediately?

You would get something like:

void doSomeProcessing(…) {
apply (TransactionProcessedEvent);
if (post-processing-required) {
apply(SomePostProcessingDoneEvent)
}
}

If the Saga deals with more than one transaction, then you really need a Saga.

I don’t really understand the problem with the associations. Let me try to explain it (hopefully in other words than I have used in the documentation).
An association consists of 2 properties: a key (or name) and a value. The key is an indication of what the value means. You could have a Saga associated with OrderId:1 as well as TransactionId:1. In both cases, the value is 1, but the key is different.
When an event arrives at a Saga, a property on that event is used to retrieve the association value of that event. This property is the association property. On the @SagaEventHandler annotation, you can also specify an “associationKey”. That is the key under which the associations of the Saga are looked up. In other words, it is that key, with the value of the association property of the event. If the Saga is associated with that association value, the saga is invoked.
However, in most cases, the associationProperty is also used as the key (since property is typically something like “transactionId”). Omitting the associationKey in the @SagaEventHandler annotation will tell Axon to use the property name as association key.

The only difference in this process is the Event that creates the Saga. Instead of doing a lookup, it will store the actual association with the Saga.

So in your scenario, you could use “aggregateIdentifier” as the association property, and “transactionId” as the association key.

Hope this helps.
Cheers,

Allard

Hi Allard,

Thank you very much for your answer and explanation! It certainly did clear up a few things :slight_smile:

Also I found this paragraph in the reference guide (4.1 Events):

"Even though the DomainEventMessage contains a reference to the Aggregate Identifier, you should always include that identifier in the actual Event itself as well. The identifier in the DomainEventMessage is meant for the EventStore and may not always provide a reliable value for other purposes. "

I probably did not explain it very well, but what I was wondering was if the Aggregate Identifier was necessary on events raised after the creation of the Saga. I had the impression that the saga could be attached to an aggregate, and subsequently handle relevant events raised on it, without necessarily having to put the Aggregate Identifier on each of these events.

Some of the post processing actions may fail at first attempt, and should be retried later (But not right away) as they depend on external systems which could be offline. Finally, different counter actions are carried out depending on whether all, some, or none of this have succeeded. I was considering using a saga (Maintaining state of the post processing) and an event scheduler for this.

Regards,

Jeppe

Hi Jeppe,

which version of Axon do you use? The text you provided comes from the Axon 2 documentation.

Cheers,

Allard

Hi again,

Ah! Sorry, forgot to clarify that part. Yes, as the text suggests I’m using 2.0 (rc-3).

Regards,

Jeppe

Hi Jeppe,

in that case, you should really consider adding the ‘aggregate identifier’ to all of your events. In fact, the wrapper Axon puts around your event should be considered an ‘axon thing’. It is something Axon needs to route a message to the correct location.

Your event should represent a fact that occurred. If something happened in a transaction, then the transactionId should be part of that event. Otherwise a listener could never know what the event really means. Relying on Axon’s aggregate identifier is not really a good idea.

About the sagas, you don’t really associate them with an aggregate, but with a concept. This may be an aggregate, but could really be anything that has an identifier. It can be part of an aggregate, an aggregate root or even something that is ‘bigger’ than an aggregate.

Hope this helps.
Cheers,

Allard