1

Consider the following code:

private readonly IEmailSender _emailSender;
public async Task Consume(ConsumeContext<UserCreated> context) // UserCreated is an event from a separate system
{
    await _dbContext.User.AddAsync(new UserAggregate { UserName = "kiddo" });
    EmailTemplate[] emailTemplates = CreateEmailTemplatePerUser();

    await _dbContext.SaveChangesAsync();
    await _emailSender.Send(emailTemplates);

}

To ensure we don't send any duplicate mails, we'd like to refactor this code and use an outbox. Resulting in the following code (simply just replacing IEmailSender with ISendEndpointProvider):

private readonly ISendEndpointProvider _sendEndpointProvider;
public async Task Consume(ConsumeContext<UserCreated> context) // UserCreated is an event from a separate system
{
    await _dbContext.User.AddAsync(new UserAggregate { UserName = "kiddo" });
    EmailCommands[] emailCommands = CreateEmailCommandPerUser();

    await _sendEndpointProvider.Send(emailCommands);
    await _dbContext.SaveChangesAsync();

}

-- Redacted Inaccurate Statement about designed behavior --

How would one go about designing this system instead? It would've been super nice to use the outbox to create multiple commands that deal with sending 1 mail individually. (our actual use case is to batch them per 100 because of 3rd party API limits but I left that out of the example for clarity)

Creating a new scope theoretically could work (since you'd no longer be in that scoped ConsumeContext) but that feels hacky and has nasty side effects when working with scoped filters.

When working with the transactional (mongo) outbox, we expect that no matter what context you're in, your messages sould be saved in the outbox.messages collection instead of instantly being sent when in a ConsumeContext.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
  • Also, your references to other stack overflow questions were related to MultiBus, and not at all relevant for regular use. – Chris Patterson Feb 20 '23 at 13:30
  • The [sample](https://github.com/MassTransit/Sample-Outbox/tree/mongodb) with MongoDB works as expected. Not sure what your issue could be if you're on the latest. – Chris Patterson Feb 21 '23 at 14:00

1 Answers1

1

This was a defect fixed in v8.0.13. When using the transactional outbox within a consumer, any dependencies using ISendEndpointProvider or IPublishEndpoint will resolve the outbox implementations.

Chris Patterson
  • 28,659
  • 3
  • 47
  • 59
  • I'm a little confused. I updated to v8.0.13 (was on v8.0.12) and the resolved `ISendEndpointProvider` is indeed different from before. It now resolves to `ConsumeContextScopedBusContext` but I don't see (or understand) how the outbox works that way. It doesn't save it to the `outbox.messages` collection but instead just puts it on the bus like a usual event unlike the `MongoDbScopedBusContext`. – Ilias Dewachter Feb 21 '23 at 09:44
  • You'd need to provide a complete example to understand why it isn't working for you (and SO isn't that place). – Chris Patterson Feb 21 '23 at 12:39