MatTheCat
MatTheCat

Reputation: 18751

How to store sagas’ data?

From what I read aggregates must only contain properties which are used to protect their invariants.

I also read sagas can be aggregates which makes sense to me.

Now I modeled a registration process using a saga: on RegistrationStarted event it sends a ReserveEmail command which will trigger an EmailReserved or EmailReservationFailed given if the email is free or not. A listener will then either send a validation link or a message telling an account already exists.

I would like to use data from the RegistrationStarted event in this listener (say the IP and user-agent). How should I do it?

Upvotes: 1

Views: 301

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57279

Rinat Abdullin wrote a good overview of sagas / process managers.

The usual answer is that the saga has copies of the events that it cares about, and uses the information in those events to compute the command messages to send.

List[Command] processManager(List[Event] events)

Pushing them through ReserveEmail command and the resulting event?

Yes, that's the usual approach; we get a list [RegistrationStarted], and we use that to calculate the result [ReserveEmail]. Later on, we'll get [RegistrationStarted, EmailReserved], and we can use that to compute the next set of commands (if any).

Sounds tedious.

The data has to travel between the two capabilities somehow. So you are either copying the data from one message to another, or you are copying a correlation identifier from one message to another and then allowing the consumer to decide how to use the correlation identifier to fetch a copy of the data.

Storing these data in the saga? But they’re not used to protect invariants.

You are typically going to be storing events in the sagas (to keep track of what has happened). That gives you a copy of the data provided in the event. You don't have an invariant to protect because you are just caching a copy of a decision made somewhere else. You won't usually have the process manager running queries to collect additional data.

What about eventual consistency?

By their nature, sagas are always going to be "eventually consistent"; the "state" of an instance of a saga is just cached copies of data controlled elsewhere. The data is probably nanoseconds old by the time the saga sees it, there's no point in pretending that the data is "now".

If I understand correctly I could model my saga as a Registration aggregate storing all the events whose correlation identifier is its own identifier?

Udi Dahan, writing about CQRS:

Here’s the strongest indication I can give you to know that you’re doing CQRS correctly: Your aggregate roots are sagas.

Upvotes: 2

Related Questions