ReliableCommandOutbox.Core
1.5.0
dotnet add package ReliableCommandOutbox.Core --version 1.5.0
NuGet\Install-Package ReliableCommandOutbox.Core -Version 1.5.0
<PackageReference Include="ReliableCommandOutbox.Core" Version="1.5.0" />
<PackageVersion Include="ReliableCommandOutbox.Core" Version="1.5.0" />
<PackageReference Include="ReliableCommandOutbox.Core" />
paket add ReliableCommandOutbox.Core --version 1.5.0
#r "nuget: ReliableCommandOutbox.Core, 1.5.0"
#:package ReliableCommandOutbox.Core@1.5.0
#addin nuget:?package=ReliableCommandOutbox.Core&version=1.5.0
#tool nuget:?package=ReliableCommandOutbox.Core&version=1.5.0
ReliableCommandOutbox
ReliableCommandOutbox es una librería .NET que implementa el Transactional Command Outbox Pattern de forma explícita, determinística y alineada con Clean Architecture.
Su objetivo es garantizar la ejecución de comandos externos críticos (no eventos) en arquitecturas distribuidas, evitando mecanismos best-effort y sin mezclar semánticas de dominio.
Motivación
En sistemas distribuidos —especialmente en contextos financieros— es común encontrar flujos donde un microservicio debe ordenar a otro sistema que ejecute una acción crítica, por ejemplo:
- Auth → Orquestador (inicio de procesos)
- Wallet → Risk Engine
- Payments → Settlement / Clearing
- Onboarding → KYC / AML
Estos flujos presentan problemas recurrentes:
- La llamada externa no puede perderse
- El flujo debe ser asincrónico
- No se puede bloquear la transacción de negocio
- Se requieren reintentos controlados
- La ejecución debe ser idempotente
- Debe existir trazabilidad y auditoría
ReliableCommandOutbox aborda estos problemas persistiendo la intención de ejecutar un comando y procesándola de forma confiable.
Qué resuelve exactamente
✔️ Garantiza que un comando externo se intente ejecutar al menos una vez
✔️ Permite retry con backoff controlado
✔️ Soporta idempotencia por business key
✔️ Evita acoplamiento directo entre microservicios
✔️ Mantiene separación clara entre dominio e infraestructura
✔️ Funciona con HTTP, gRPC, colas u otros transportes
Qué NO es esta librería
Es importante dejar explícitos los límites:
- ❌ No es un bus de eventos
- ❌ No reemplaza mensajería (Kafka, RabbitMQ, etc.)
- ❌ No ejecuta lógica de negocio
- ❌ No implementa sagas
- ❌ No incluye scheduling (Quartz, cron, timers)
- ❌ No asume transporte alguno
- ❌ No registra implementaciones automáticamente
La librería garantiza el “cómo”.
El microservicio decide el “qué”, el “cuándo” y el “hacia dónde”.
Principios de diseño
- Clean Architecture
- Ports & Adapters
- Fail-fast
- Determinismo
- Idempotencia explícita
- Sin dependencias de infraestructura
- Reutilizable vía NuGet
- Auditable y defendible en producción
Arquitectura interna
Abstractions
Define el contrato público consumido tanto por el motor como por los microservicios:
CommandOutboxRecordOutboxStatusICommandOutboxRepositoryICommandDispatcherIRetryPolicyIClockOutboxExecutionResult
No contienen lógica ni dependencias externas.
Core
Implementa el motor determinístico:
OutboxStateMachineRetryCoordinatorRetryDecisionOutboxProcessor
Coordina persistencia, ejecución, estados y reintentos sin conocer detalles técnicos.
Extensions
Facilita el wiring explícito en DI:
AddReliableCommandOutbox<TRecord>()
No registra infraestructura ni asume implementaciones.
Modelo estructural (contratos y relaciones)
classDiagram
direction TB
%% =========================
%% ABSTRACTIONS
%% =========================
class OutboxStatus {
<<enum>>
Pending
Processing
Sent
Failed
Dead
}
class CommandOutboxRecord {
<<abstract>>
+Guid Id
+string CommandName
+string Target
+string Payload
+string BusinessKey
+OutboxStatus Status
+int RetryCount
+int MaxRetries
+DateTime NextAttemptAt
+DateTime CreatedAt
+DateTime? ProcessedAt
+string? LastError
}
class OutboxExecutionResult {
+bool Success
+bool Retryable
+string? Error
+Succeeded()
+RetryableFailure(string)
+TerminalFailure(string)
}
class ICommandOutboxRepository~TRecord~ {
<<interface>>
+AddAsync(TRecord)
+FetchNextAsync()
+MarkProcessingAsync(Guid)
+MarkAsSentAsync(Guid)
+MarkAsFailedAsync(Guid, string)
+MarkAsDeadAsync(Guid, string)
+ScheduleRetryAsync(Guid, DateTime, string)
}
class ICommandDispatcher~TRecord~ {
<<interface>>
+DispatchAsync(TRecord)
}
class IRetryPolicy {
<<interface>>
+ShouldRetry(int, Exception?, OutboxExecutionResult?)
+CalculateNextAttempt(int, DateTime)
}
class IClock {
<<interface>>
+UtcNow : DateTime
}
%% =========================
%% CORE
%% =========================
class OutboxProcessor~TRecord~ {
+ProcessNextAsync()
}
%% =========================
%% RELATIONSHIPS
%% =========================
CommandOutboxRecord --> OutboxStatus
ICommandOutboxRepository~TRecord~ ..> CommandOutboxRecord
ICommandDispatcher~TRecord~ ..> CommandOutboxRecord
ICommandDispatcher~TRecord~ ..> OutboxExecutionResult
IRetryPolicy ..> OutboxExecutionResult
OutboxProcessor~TRecord~ ..> ICommandOutboxRepository~TRecord~
OutboxProcessor~TRecord~ ..> ICommandDispatcher~TRecord~
OutboxProcessor~TRecord~ ..> IRetryPolicy
OutboxProcessor~TRecord~ ..> IClock
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- ReliableCommandOutbox.Abstractions (>= 1.5.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ReliableCommandOutbox.Core:
| Package | Downloads |
|---|---|
|
ReliableCommandOutbox.Extensions
Extensiones de integración para registrar el motor ReliableCommandOutbox en Microsoft.Extensions.DependencyInjection. |
GitHub repositories
This package is not used by any popular GitHub repositories.