LilHermes 2.1.0

dotnet add package LilHermes --version 2.1.0
                    
NuGet\Install-Package LilHermes -Version 2.1.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="LilHermes" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LilHermes" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="LilHermes" />
                    
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 LilHermes --version 2.1.0
                    
#r "nuget: LilHermes, 2.1.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 LilHermes@2.1.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=LilHermes&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=LilHermes&version=2.1.0
                    
Install as a Cake Tool

LilHermes

Wrapper ligero de RabbitMQ para .NET Standard 2.0. Proporciona abstracciones de publicación y consumo de mensajes con soporte nativo de trazabilidad distribuida (OpenTelemetry) y Dead-Letter Queue (DLQ).


Contenido


Requisitos

  • .NET Standard 2.0 (aplicaciones .NET 6+, .NET Framework 4.6.1+)
  • RabbitMQ corriendo y accesible
  • (Opcional) Colector OTLP en http://localhost:4318 para trazas

Proyectos

Paquete Descripción
LilHermes.Abstractions Contratos: MessageBusOptions, MessageContext<T>, enums
LilHermes.Infrastructure Implementaciones: publisher, consumer, connection manager, telemetría

Instalación vía DI

Registra los servicios en Program.cs o en tu Startup.cs:

// Publisher + Consumer (stack completo)
builder.Services.AddLilHermes(options =>
{
    options.ConnectionOptions.HostName = "localhost";
    options.ConnectionOptions.Username = "guest";
    options.ConnectionOptions.Password = "guest";

    options.PublishOptions.Exchange    = "mi-exchange";
    options.PublishOptions.ExchangeType = RabbitMQExchangeType.Direct;

    options.ConsumerOptions.QueueName  = "mi-cola";
    options.ConsumerOptions.ExchangeName = "mi-exchange";
});

// Solo publisher
builder.Services.AddLilHermesPublisher(options => { ... });

// Solo consumer
builder.Services.AddLilHermesConsumer(options => { ... });

Configuración

Conexión (ConnectionOptions)

Propiedad Default Descripción
HostName 127.0.0.1 Host del broker
Port 5672 Puerto AMQP
Username / Password guest Credenciales
VirtualHost / VHost de RabbitMQ
ConnectionUri — URI completa (alternativa a host/port)
EnabledCluster false Activa modo clúster
Endpoints — Lista de nodos del clúster
AutomaticRecoveryEnabled true Reconexión automática
NetworkRecoveryInterval 5s Intervalo entre reintentos de reconexión

Publicación (PublishOptions)

Propiedad Default Descripción
Exchange — Nombre del exchange
ExchangeType — Direct, Topic, Fanout, Headers
Persistent true Mensajes persistentes en disco
PublisherConfirmationsEnabled true Confirmaciones del broker
Priority Normal Low, Normal, High

Consumo (ConsumerOptions)

Propiedad Default Descripción
QueueName LilHermes-Queue-v0 Nombre de la cola
ExchangeName — Exchange al que se vincula
RoutingKeys — Claves de enrutamiento
AcknowledgeMode Manual Auto o Manual
PrefetchCount 100 Mensajes prefetcheados por consumer
MaxRetryCount 3 Reintentos antes de enviar a DLQ
RetryDelayMs 1000 Delay entre reintentos (ms)
EnableDLQ false Habilita Dead-Letter Queue
MessageTTL 30000 TTL de mensajes en cola de retry (ms)

Publicar mensajes

Inyecta IMessagePublisher y crea el mensaje con MessageContext.Create:

public class MiServicio(IMessagePublisher publisher)
{
    public async Task EnviarPedidoAsync(Pedido pedido, CancellationToken ct)
    {
        // CorrelationId, MessageId y Timestamp (UTC) se generan automáticamente
        var mensaje = MessageContext.Create(pedido, "servicio-pedidos");

        await publisher.PublishAsync(mensaje, routingKey: "pedidos.nuevo", ct);
    }
}

Si el mensaje ya tiene un id propio (por ejemplo, el id del documento), pásalo como tercer argumento: MessageContext.Create(pedido, "servicio-pedidos", pedido.Id.ToString()). Desde la 2.1.0, Timestamp se genera en UTC.

Publicación en lote

var mensajes = pedidos.Select(p => MessageContext.Create(p, "servicio-pedidos"));
await publisher.PublishBatchAsync(mensajes, routingKey: "pedidos.lote", ct);

Consumir mensajes

Modo simple (solo el payload)

public class MiConsumerService(IMessageConsumer consumer) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        await consumer.StartConsumingAsync<Pedido>(
            async (pedido, deliveryTag) =>
            {
                // Procesar pedido
                await ProcesarAsync(pedido);
                await consumer.AckAsync(deliveryTag);
            },
            ct);
    }
}

Modo con contexto (acceso a metadatos y trazas)

await consumer.StartConsumingWithContextAsync<Pedido>(
    async (context, deliveryTag) =>
    {
        var correlationId = context.CorrelationId;
        var pedido = context.Data;

        await ProcesarAsync(pedido);
        await consumer.AckAsync(deliveryTag);
    },
    ct);

Dead-Letter Queue

Cuando EnableDLQ = true, LilHermes crea automáticamente la siguiente infraestructura en RabbitMQ:

[Exchange principal] → [Cola principal]
                              ↓ (fallo)
                       [Cola de retry] ← TTL → [Exchange principal]
                              ↓ (MaxRetryCount agotado)
                       [Cola parqueada (errores)]

Activa DLQ en la configuración del consumer:

options.ConsumerOptions.EnableDLQ      = true;
options.ConsumerOptions.MaxRetryCount  = 3;
options.ConsumerOptions.RetryDelayMs   = 2000;
options.ConsumerOptions.MessageTTL     = 60000;

Los mensajes que superan MaxRetryCount quedan en la cola {QueueName}.error para inspección manual.


OpenTelemetry

LilHermes instrumenta automáticamente la publicación y el consumo con System.Diagnostics (ActivitySource y Meter). No depende de los paquetes de OpenTelemetry: cada servicio usa la versión de OpenTelemetry que necesite y registra LilHermes por nombre.

El nombre es el SourceName configurado en AddLilHermes (por defecto LilHermesTelemetry.DefaultSourceName, es decir "LilHermes"). Trazas y métricas usan el mismo nombre.

Registrar trazas y métricas

builder.Services.AddLilHermes(options =>
{
    options.SourceName = "MiServicio";
    // ...
});

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("MiServicio")   // <-- trazas de LilHermes
        .AddOtlpExporter())
    .WithMetrics(metrics => metrics
        .AddMeter("MiServicio")    // <-- métricas de LilHermes
        .AddOtlpExporter());

Migración de 1.x a 2.0

En la 2.0 se eliminó AddLilHermesInstrumentation junto con la dependencia de OpenTelemetry.Api (CVE-2026-40894). Reemplázala por AddSource con el mismo SourceName que configuras en AddLilHermes:

// 1.x
.AddLilHermesInstrumentation("MiServicio")
// 2.0
.AddSource("MiServicio")

Si llamabas a AddLilHermesInstrumentation() sin argumento, el nombre era "LilHermes": comprueba que coincida con tu SourceName; si no coincidía, las trazas de LilHermes no se estaban exportando.

Métricas disponibles

Métrica Tipo Descripción
messages_published Counter Mensajes publicados
messages_consumed Counter Mensajes consumidos
messages_failed Counter Mensajes fallidos
publish_duration_ms Histogram Duración de publicación

Tags de trazas (OTel Semantic Conventions)

  • messaging.system, messaging.destination, messaging.routing_key
  • messaging.message_id, messaging.correlation_id
  • rabbitmq.exchange, rabbitmq.queue

La propagación de contexto usa el estándar W3C Trace Context (traceparent / tracestate) a través de los headers AMQP.


Comandos de desarrollo

# Compilar la solución
dotnet build LilHermes.sln

# Ejecutar todos los tests
dotnet test LilHermes.sln

# Solo tests unitarios
dotnet test test/LilHermes.UnitTests/LilHermes.UnitTests.csproj

# Solo tests de integración (requiere RabbitMQ + colector OTLP en localhost:4318)
dotnet test test/LilHermes.IntegrationTests/LilHermes.IntegrationTests.csproj

# Filtrar por nombre de test
dotnet test LilHermes.sln --filter "FullyQualifiedName~NombreDelTest"

# Generar paquetes NuGet
dotnet pack LilHermes.sln

Tests

Proyecto Target Requisitos
LilHermes.UnitTests net8.0 Ninguno
LilHermes.IntegrationTests net8.0 RabbitMQ + OTLP en localhost:4318

Para levantar RabbitMQ rápidamente con Docker:

docker run -d --name rabbitmq \
  -p 5672:5672 -p 15672:15672 \
  rabbitmq:3-management

Panel de administración disponible en http://localhost:15672 (guest/guest).


Estructura del proyecto

LilHermes/
├── src/
│   ├── LilHermes.Abstractions/       # Contratos y modelos
│   │   ├── Entities/                 # MessageBusOptions, MessageContext<T>, etc.
│   │   └── Enums/                    # RabbitMQExchangeType, AcknowledgeMode, MessagePriority
│   └── LilHermes.Infrastructure/     # Implementaciones
│       ├── Connections/              # RabbitMQConnectionManager
│       ├── Publishers/               # RabbitMQPublisher
│       ├── Consumers/                # RabbitMQConsumer
│       ├── Extensions/               # LilHermesExtensions (DI)
│       └── Telemetry/                # ActivitySource, Meter, propagación W3C
└── test/
    ├── LilHermes.UnitTests/
    └── LilHermes.IntegrationTests/
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 0 10/3/2026
2.0.0 0 10/3/2026
1.0.0 158 3/11/2026 1.0.0 is deprecated because it has critical bugs.

2.1.0 — nuevo MessageContext.Create(data, sourceService, messageId) para armar mensajes sin escribir el tipo genérico; reemplaza los MessageContextFactory propios de cada servicio. MessageContext<T>.Timestamp ahora se genera en UTC (antes hora local); el header AMQP no cambia.