MassTransit adapter

BabelQueue.MassTransit plugs the .NET core into MassTransit. It registers a System.Text.Json converter that reads/writes the canonical envelope byte-for-byte, switches the bus to raw JSON, and adds an ergonomic publisher.

Install

dotnet add package BabelQueue.MassTransit

Requirements: .NET 8, MassTransit 8+. BabelQueue.Core comes transitively.

Configuration

Call UseBabelQueueEnvelopes() inside your bus configurator and register the publisher:

using BabelQueue.MassTransit;

builder.Services.AddMassTransit(x =>
{
    x.UsingRabbitMq((context, cfg) =>
    {
        cfg.UseBabelQueueEnvelopes();   // canonical envelope on the wire (raw JSON)
        cfg.ConfigureEndpoints(context);
    });
});

builder.Services.AddBabelQueuePublisher(defaultQueue: "orders");

UseBabelQueueEnvelopes() adds BabelEnvelopeJsonConverter to MassTransit’s SystemTextJsonMessageSerializer.Options and calls UseRawJsonSerializer(), so the wire body is the bare canonical envelope (no MassTransit wrapper).

Produce

Inject BabelQueuePublisher; PublishAsync(...) returns meta.id:

using BabelQueue.MassTransit;

public class Orders(BabelQueuePublisher babelQueue)
{
    public Task Create() =>
        babelQueue.PublishAsync(
            "urn:babel:orders:created",
            new Dictionary<string, object?> { ["order_id"] = 1042L },
            "orders");
}

Overloads: PublishAsync(urn, data, ct?) (default queue) and PublishAsync(urn, data, queue, traceId?, ct?).

Consume

Implement IConsumer<Envelope> (the core type, namespace BabelQueue) and route by URN with EnvelopeCodec.Urn(...):

using BabelQueue;
using MassTransit;

public class OrderConsumer : IConsumer<Envelope>
{
    public Task Consume(ConsumeContext<Envelope> context)
    {
        var envelope = context.Message;
        if (!EnvelopeCodec.Accepts(envelope)) return Task.CompletedTask;

        switch (EnvelopeCodec.Urn(envelope))
        {
            case "urn:babel:orders:created":
                // use envelope.Data, envelope.TraceId …
                break;
        }
        return Task.CompletedTask;
    }
}

Standalone converter

The converter also works with plain System.Text.Json, no bus required:

var options = new JsonSerializerOptions().AddBabelQueueEnvelopes();
string wire = JsonSerializer.Serialize(envelope, options); // == EnvelopeCodec.Encode(envelope)

The wire body is the canonical envelope (meta.lang "dotnet"), so it interoperates with every other BabelQueue SDK.