Azure Service Bus transport
BabelQueue.AzureServiceBus is an Azure Service Bus transport on the .NET core. It sends
the canonical envelope as the Body with the
§4 native projection, and consumes by
routing each message to a handler by URN — so a message it produces is consumed by any
other BabelQueue SDK, and vice-versa.
Install
dotnet add package BabelQueue.AzureServiceBus
Requirements: .NET 8. It pulls BabelQueue.Core and Azure.Messaging.ServiceBus
transitively.
Produce
using Azure.Messaging.ServiceBus;
using BabelQueue.AzureServiceBus;
await using var client = new ServiceBusClient("<connection-string>"); // or a namespace + TokenCredential
var sender = client.CreateSender("orders");
var id = await new AsbPublisher(sender)
.PublishAsync("urn:babel:orders:created", new Dictionary<string, object?> { ["order_id"] = 1042 });
PublishAsync returns the message meta.id; pass a traceId to continue a trace, or a
delay (TimeSpan) to schedule native delayed delivery (ScheduledEnqueueTime).
Consume
var receiver = client.CreateReceiver("orders"); // PeekLock
var handlers = new Dictionary<string, BabelHandler>
{
["urn:babel:orders:created"] = (envelope, message, ct) =>
{
// envelope.Data, envelope.TraceId, envelope.Attempts ...
return Task.CompletedTask;
},
};
var consumer = new AsbConsumer(receiver, handlers, new AsbConsumerOptions
{
OnError = (err, env, msg) => Console.Error.WriteLine(err),
});
await consumer.RunAsync(cancellationToken);
A throwing handler Abandons the message — the broker redelivers it and increments
DeliveryCount (at-least-once); at MaxDeliveryCount it auto-moves to the native
dead-letter sub-queue. Auth is a connection string or the fully-qualified namespace + a
TokenCredential (DefaultAzureCredential).
Contract mapping (§4)
| Envelope | Azure Service Bus |
|---|---|
| body | Body (byte-identical across SDKs) |
job (URN) | Subject |
trace_id | CorrelationId |
meta.id | MessageId |
meta.schema_version | ApplicationProperties["bq-schema-version"] |
meta.lang | ApplicationProperties["bq-source-lang"] |
meta.created_at | ApplicationProperties["bq-created-at"] (ms) |
attempts | max(body, DeliveryCount − 1) |
| reserve / ack / retry | PeekLock → Complete / Abandon |
ServiceBusSender / ServiceBusReceiver are mockable, so the unit tests use Moq +
ServiceBusModelFactory — no Azure, no network. The envelope is unchanged
(schema_version stays 1); Azure Service Bus is purely additive.