Ensuring consistency using NServiceBus with AWS SQS transport


(Martin Oskarsson) #1

Consider this simple scenario:

HTTP PUT request is called on a “CreateUser” API.
When handling that request in the controller, we want to
a) store the business data changes
b) publish integration events to multiple subscribers after the fact

public async Task<IActionResult> CreateUser(...
	// a: store the business data changes in a postgresql db
	await userRepository.Save(user);
	// b: publish integration events to multiple subscribers after the fact, using NServiceBus/SQS
	foreach (var @event in user.Events)
		await context.Publish(@event);

The system (the publisher and all subscribers) needs to be eventual consistent, so:
If “a” fails, we don’t want to publish an event. Easy.

But if “b” fails, we are screwed, especially if some of the Publish calls already suceeded.
Usually I would solve this by using an outbox pattern and publish the messages in a completely seperate process.
But I was wondering if NServiceBus already had an answer to this common challenge? Something in the line of what “Jasper” supports: https://jeremydmiller.com/2018/04/16/jaspers-outbox-pattern-support/

I know NServiceBus has an outbox feature, but it only works within a message handler context so it does not really apply to this scenario.

(Mauro Servienti) #2

Hi Martin,

An easy way to decouple the business process from the incoming HTTP request is by sending a message locally to yourself and then in the context of that message do what you plan to do using also the Outbox.


(Martin Oskarsson) #3

Good idea.
I already use a command pattern internally in the service (using something like MediatR). I guess if I just replaced the MediatR style plumming with some “SendLocal” NServiceBus stuff, I would be flying :slight_smile:

(Andreas Öhlund) #4

Also note that the Jasper/Marten “outbox” is slightly different in that it doesn’t (yet) have any deduplication support should you need that