Salvatore Calla'
Salvatore Calla'

Reputation: 153

MassTransit Transactional OutBox

I'm trying to implement the MassTransit Transactional Outbox pattern in my application.

I want to create a .net web API application that receives a request and, using the IPublishEndpoint interface stores the messages in the OutboxMessage table.

In a separate console application, I want to implement the background worker that reads the messages from the OutboxMessage table and, using RabbitMQ sends them in a queue. I configured my API in this way:

Program.cs

using MassTransit;
using Microsoft.EntityFrameworkCore;
using TransactionalOutboxApi.Data;
using TransactionalOutboxApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();


builder.Services.AddMassTransit(cfg =>
{
    cfg.SetKebabCaseEndpointNameFormatter();

    cfg.AddEntityFrameworkOutbox<AppDbContext>(options =>
    {
        options.UseSqlServer();
        options.UseBusOutbox(o => o.DisableDeliveryService());
    });

    cfg.UsingRabbitMq((context, cfg) =>
    {
        cfg.Host("localhost", h =>
        {
            h.Username("guest");
            h.Password("guest");
        });


        cfg.ConfigureEndpoints(context);
    });

});

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer("Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=MassTransit;Integrated Security=True;Connect Timeout=60;"));

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapPost("/events", async (ApiRequest dto, AppDbContext dbContext, IPublishEndpoint publish) =>
{
    var message = new OutboxMessage { Id = Guid.NewGuid(), Message = dto.Message, CreatedAt = DateTime.UtcNow };

    await publish.Publish(message); // Scrive nella Outbox, non invia subito

    await dbContext.SaveChangesAsync(); // Commit della transazione

    return Results.Ok(new { Message = "Event saved in Outbox" });
});

app.Run();

What is not clear to me is why, to run the application, I need to use something like RabbitMQ although I don't need to send messages to RabbitMQ from the API project. If I omit this, I receive an error like the following:

System.AggregateException: 
'Some services are not able to be constructed 
(Error while validating the service descriptor 'ServiceType: 
MassTransit.DependencyInjection
.IScopedBusContextProvider`1[MassTransit.IBus] Lifetime: 
Scoped ImplementationType: 
MassTransit.EntityFrameworkCoreIntegration
.EntityFrameworkScopedBusContextProvider`2[MassTransit.IBus,
TransactionalOutboxApi.Data.AppDbContext]': 
Unable to resolve service for type 
'MassTransit.IBus' while attempting to activate 'MassTransit.EntityFrameworkCoreIntegration.
EntityFrameworkScopedBusContextProvider`2[MassTransit.IBus,
TransactionalOutboxApi.Data.AppDbContext]'.)'

Any help?

Upvotes: 0

Views: 38

Answers (0)

Related Questions