SAGA handling events that may or may not be part of 'saga'

So during a customer enrollment process I have a couple of actions like updateLogin, updateEmail that need to occur before we send a notification to the customer. We collected all the needed data and post a big bang submission to an api. We save the core data, then can fire off the secondary items via messages. So using a SAGA we wait to hear from loginUpdated, emailUpdated events before firing a CustomerCreationCompleted event which then triggers a formal notification to the customer.

My question stems from post enrollment. The customer may later decide to change their email. We handle that action with the same logic and fire the same emailUpdated event. Even though this time its not part of my “enrollment” process, given it’s the same message would the SAGA handler essentially still ‘process’ it but just ignore it since it cant find it. Is that ok, or is that creating a level of extra I/O that should be avoided.

I’ve thought about having the SAGA only started with some “EnrollmentStarted” event, that fires off the needed updateLogin/Email commands. But still the SAGA has to listen for those return events to flip the booleans. So whether the SAGA is started with all the possible events or from some master starter event, it seems like my non-saga events would still somehow flow through some portion of the saga handler since it’s the same message.

I was hoping to avoid some duplicate messages… emailUpdatedPerEnrollment , emailUpdatePerNormalUsage… that would naturally create the separation but I’m struggling to find the right answer.

Hey @StephenB, good to see you.

I understand the struggle. However, one could argue that emailUpdated is not a good-looking business event. On the other hand, emailUpdatedPerEnrollment and emailUpdatePerNormalUsage are much better. They clearly explain what’s happening and why in contrast to the former, which looks much more like a technical event (someone updated a field in a database).

If your concern is related to the fact that the two processes will look very similar in the beginning, I’d argue that’s fine. They will probably diverge over time.

What do you think?

Thanks for the insight and reminder that we’re handling business processes not just technical event. I’ll will further refine.

I’m thinking that it might be possible to simplify or improve this design somewhat.

I have some questions, though.

If as a part of enrolling a new user you’re collecting all the data, sending it through an API, and presumably saving that to a database directly, why is it necessary to raise events like LoginUpdated and EmailUpdated, since this is specifically for a new user enrollment process? What kind of logic do you have processing the LoginUpdated and EmailUpdated events, other than the saga?

Could you clarify what the saga is doing as a part of the enrollment process? If it’s just publishing the CustomerCreated event after getting the LoginUpdated and EmailUpdated events, presumably the API could just publish the CustomerCreated event itself.

Or, is the saga doing a kind of email verification process? Loosely described, the saga being kicked off by a command like SubmitEmail, which would open a timeout (let’s say 24 hours) so that you could clean things up if the user doesn’t verify their email, and send a VerifyEmailRequest to another endpoint which would send the “click here to verify” email. When the user clicks that link, that would go to an API would be publish an EmailVerified event, which the saga endpoint is subscribed to, which would then complete and publish some kind of event like EmailConfirmed.

But, if it’s doing that, it shouldn’t really be doing anything else.

So, it seems like we’d need some more context to make more specific recommendations for your situation.

Kind regards,

We are working with a 3rd party that actually stores the core data. For the LoginUpdated part, we populate the user’s LoginName field with their ID#, but that isn’t known till after it’s created in the DB (it’s just an identity field). After the successful enrollment (saving data, charging CC# etc) we have to go back to update that newly created record with that ID# value into the LoginName field as their initial LoginName. Its goofy, but it’s not a process we can change at this point.

In order to get back to the calling customer quickly and not risk failed transactions after charging their CC, we are wanting to handle these “housekeeping” tasks in the background.

Some of those tasks are activities like provisioning special login tokens for another 3rd party mobile app, recording legal acceptance flags with 3rd party, all those we want to complete before we trigger any official ‘all done’ events.

I was looking to use the SAGA to ensure all those little things were completed before sending a final “EnrollmentTotallyCompleted” event.

Some of those cases the customer might update after enrollment in the normal lifecycle… change their loginname or need to accept new legal terms and flags… all essentially the same data and process as done during enrollment. But in these cases, they are just stand-alone events.

Hope that gives a little more context, thanks.

That context is helpful. Thanks.

Using a saga in these kinds of integration scenarios does make sense. That being said, I’d suggest using a request/reply semantic as opposed to events for these integration parts. It can help differentiate the integration flows from the higher-level logical pub/sub you’d prefer to do between logically-independent “services”.

Also, the enrollment process you’re describing sounds like something that would be well designed as a front-end composition of components from those multiple logical services.

This presentation describes how something like that could work: