BabelQueue.Core 1.4.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package BabelQueue.Core --version 1.4.0
                    
NuGet\Install-Package BabelQueue.Core -Version 1.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="BabelQueue.Core" Version="1.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BabelQueue.Core" Version="1.4.0" />
                    
Directory.Packages.props
<PackageReference Include="BabelQueue.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add BabelQueue.Core --version 1.4.0
                    
#r "nuget: BabelQueue.Core, 1.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package BabelQueue.Core@1.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=BabelQueue.Core&version=1.4.0
                    
Install as a Cake Addin
#tool nuget:?package=BabelQueue.Core&version=1.4.0
                    
Install as a Cake Tool

BabelQueue for .NET

CI NuGet License: MIT

Polyglot Queues, Simplified. Read and write the canonical BabelQueue message envelope from .NET — so your C#/.NET services exchange messages with Laravel, Symfony, Python, Go, Node and Java over one strict JSON format, on the broker you already run.

This is the framework-agnostic .NET core: the wire-envelope codec, contracts and dead-letter helpers — zero dependencies (in-box System.Text.Json only). The full standard is documented at babelqueue.com.

Installation

dotnet add package BabelQueue.Core

Targets .NET 8.

Usage

using BabelQueue;

// Produce — build the canonical envelope and publish the JSON to your broker.
var env = EnvelopeCodec.Make(
    "urn:babel:orders:created",
    new Dictionary<string, object?> { ["order_id"] = 1042L },
    queue: "orders");
string body = EnvelopeCodec.Encode(env); // compact UTF-8 JSON
// await db.ListRightPushAsync("queues:orders", body);
//   /  channel.BasicPublish("", "orders", props, Encoding.UTF8.GetBytes(body));

// Consume — decode a message produced by ANY BabelQueue SDK.
var incoming = EnvelopeCodec.Decode(body);
if (EnvelopeCodec.Accepts(incoming))
{
    switch (EnvelopeCodec.Urn(incoming))
    {
        case "urn:babel:orders:created":
            Console.WriteLine($"{incoming.Data!["order_id"]} {incoming.TraceId}");
            break;
    }
}

The envelope is identical to every other SDK's:

{
  "job": "urn:babel:orders:created",
  "trace_id": "…",
  "data": { "order_id": 1042 },
  "meta": { "id": "…", "queue": "orders", "lang": "dotnet", "schema_version": 1, "created_at": 1749132727000 },
  "attempts": 0
}

JSON numbers decode into Data as long (integers) or double (decimals); objects as Dictionary<string, object?> (insertion order preserved). Encode uses UnsafeRelaxedJsonEscaping, so slashes and non-ASCII stay literal and the bytes match the PHP/Python/Node/Java cores.

Typed messages (optional)

public sealed class OrderCreated(long orderId) : IPolyglotMessage, IHasTraceId
{
    public string GetBabelUrn() => "urn:babel:orders:created";
    public IReadOnlyDictionary<string, object?> ToPayload() =>
        new Dictionary<string, object?> { ["order_id"] = orderId };
    public string? GetBabelTraceId() => null; // or an inbound trace to continue
}

var env = EnvelopeCodec.FromMessage(new OrderCreated(1042L), "orders");

Dead-letter

var dlq = DeadLetters.Annotate(env, "failed", "orders", attempts: 3, error: "boom");
// publish EnvelopeCodec.Encode(dlq) to the "orders.dlq" queue

DeadLetters.Annotate returns a copy — the original envelope is preserved unchanged inside the dead-lettered message, so any-language consumers can still read it.

What this core is (and isn't)

It enforces the contract: the envelope shape, URN identity, trace propagation, schema-version gating and the dead-letter block. It is intentionally not a worker/runtime — broker wiring, acks and retry loops stay in your own code (or a future adapter), exactly as with the other SDK cores.

UnknownUrnStrategy (Fail, Delete, Release, DeadLetter) is provided for adapters to act on.

OpenTelemetry tracing (optional)

BabelQueue.Tracing adds opt-in OpenTelemetry tracing built only on the in-box System.Diagnostics.Activity — the primitive the OpenTelemetry .NET SDK consumes — so the core still takes zero package dependencies. To export, wire a TracerProvider that listens to the source Telemetry.ActivitySourceName ("BabelQueue", e.g. .AddSource("BabelQueue")); with no listener the helpers are nearly free and emit nothing. The wire envelope is never touched.

Cross-hop propagation works at two layered levels:

  • trace_id correlation (v0.1): Telemetry.Wrap/Telemetry.PublishAsync map the envelope's trace_id to an OTel trace id, so every hop that shares a trace_id shares one trace — correlation and per-hop timing.
  • W3C traceparent span linkage (v0.2): the header-aware overloads carry the active span across a hop as a W3C traceparent on an out-of-band header carrier that rides beside the frozen envelope (never inside it), so the consumer span becomes a true child of the producer span. No header ⇒ it falls back to the v0.1 trace_id parent — a strict, backward-compatible upgrade.
using BabelQueue.Tracing;

// PRODUCER — inject the active span's traceparent into a carrier the adapter
// carries on the transport's metadata channel, beside the envelope.
var headers = new Dictionary<string, string>();
string id = await Telemetry.PublishAsync(
    "urn:babel:orders:created",
    new Dictionary<string, object?> { ["order_id"] = 1042L },
    headers,                                   // <- the out-of-band carrier
    env => myTransport.SendAsync(env, headers), // adapter carries `headers`
    queue: "orders");

// CONSUMER — pass the delivered message's headers; the process span is started
// as a child of the producer span (or the trace_id parent when absent).
Handler traced = Telemetry.Wrap(async env => { /* handle */ }, deliveredHeaders);
await traced(incoming);

The carrier is IDictionary<string,string> to write (producer) / IReadOnlyDictionary<string,string> to read (consumer) — the .NET counterpart of the Go HeaderPublisher/ReceivedMessage.Headers and Node HeaderCarrier seams. Traceparent.Inject / Traceparent.RemoteParentFromHeaders expose the W3C inject/extract directly. Per-adapter transport wiring (the .NET transports live in the separate BabelQueue.Sqs / BabelQueue.Redis / BabelQueue.MassTransit packages) is a documented follow-up; this core ships the mechanism.

Conformance

This core passes the shared cross-SDK conformance suite (vendored under tests/BabelQueue.Core.Tests/conformance/) — the same fixtures every BabelQueue SDK must satisfy, so a .NET producer and, say, a Laravel consumer agree byte-for-byte.

dotnet test

License

MIT © Muhammet Şafak

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on BabelQueue.Core:

Package Downloads
BabelQueue.MassTransit

MassTransit adapter for BabelQueue — a System.Text.Json converter, publisher and configuration so MassTransit services produce/consume the canonical BabelQueue wire envelope.

BabelQueue.Redis

Redis transport for BabelQueue — a canonical-envelope publisher and a URN-routed consumer over StackExchange.Redis (the reliable-queue list pattern), on the framework-agnostic core.

BabelQueue.Sqs

Amazon SQS transport for BabelQueue — a canonical-envelope publisher and a URN-routed consumer over the AWS SDK for .NET, on the framework-agnostic core.

BabelQueue.Pulsar

Apache Pulsar transport for BabelQueue — a canonical-envelope publisher and a URN-routed consumer over DotPulsar, on the framework-agnostic core.

BabelQueue.AzureServiceBus

Azure Service Bus transport for BabelQueue — a canonical-envelope publisher and a URN-routed consumer over Azure.Messaging.ServiceBus, on the framework-agnostic core.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.7.0 137 6/21/2026
1.6.0 114 6/21/2026
1.5.0 115 6/21/2026
1.4.0 203 6/20/2026
1.3.0 106 6/19/2026
1.2.0 111 6/19/2026
1.1.0 132 6/18/2026
1.0.0 407 6/7/2026
0.1.0 144 6/6/2026