Cosmos.EventSourcing.CritterStack
0.0.7
dotnet add package Cosmos.EventSourcing.CritterStack --version 0.0.7
NuGet\Install-Package Cosmos.EventSourcing.CritterStack -Version 0.0.7
<PackageReference Include="Cosmos.EventSourcing.CritterStack" Version="0.0.7" />
<PackageVersion Include="Cosmos.EventSourcing.CritterStack" Version="0.0.7" />
<PackageReference Include="Cosmos.EventSourcing.CritterStack" />
paket add Cosmos.EventSourcing.CritterStack --version 0.0.7
#r "nuget: Cosmos.EventSourcing.CritterStack, 0.0.7"
#:package Cosmos.EventSourcing.CritterStack@0.0.7
#addin nuget:?package=Cosmos.EventSourcing.CritterStack&version=0.0.7
#tool nuget:?package=Cosmos.EventSourcing.CritterStack&version=0.0.7
Cosmos.EventSourcing.CritterStack
Implementación completa de Event Sourcing y CQRS usando Wolverine y Marten (CritterStack).
Descripción
Este paquete proporciona implementaciones listas para producción de todas las abstracciones definidas en Cosmos.EventSourcing.Abstractions y Cosmos.EventDriven.Abstractions. Utiliza Wolverine para mensajería y mediación, y Marten como Event Store y Document Database sobre PostgreSQL.
CritterStack es el nombre de la combinación de Wolverine + Marten, dos poderosas herramientas del ecosistema .NET.
Características
Event Store
- MartenEventStore: Implementación de
IEventStoreusando Marten - Soporte para recuperar agregados por ID, versión o timestamp
- Persistencia de eventos en PostgreSQL
Command Routing
- WolverineCommandRouter: Router de comandos usando Wolverine
- Soporte para comandos con y sin valor de retorno
- Integración con multi-tenancy
Query Routing
- WolverineQueryRouter: Router de consultas usando Wolverine
- Ejecución distribuida de queries
Event Publishing
- WolverineEventSender: Publicación de eventos usando Wolverine
- Integración con RabbitMQ para mensajería distribuida
- Soporte para multi-tenancy
Projection Store
- MartenProjectionStore: Almacén de proyecciones usando Marten
- Operaciones CRUD sobre proyecciones/vistas de lectura
Instalación
dotnet add package Cosmos.EventSourcing.CritterStack
Este paquete incluye automáticamente las dependencias de:
- Cosmos.EventSourcing.Abstractions
- Cosmos.EventDriven.Abstractions
- Cosmos.MultiTenancy
Configuración
Registrar Servicios en el DI Container
using Marten;
using Wolverine;
using Cosmos.EventSourcing.CritterStack.Commands;
using Cosmos.EventSourcing.CritterStack.Queries;
using Cosmos.EventSourcing.CritterStack.Routers;
var builder = WebApplication.CreateBuilder(args);
// Configurar Marten
builder.Services.AddMarten(options =>
{
options.Connection(builder.Configuration.GetConnectionString("Postgres")!);
// Configurar Event Store
options.Events.StreamIdentity = StreamIdentity.AsString;
// Registrar agregados
options.Events.AddEventType<OrderCreated>();
options.Events.AddEventType<ItemAdded>();
});
// Configurar Wolverine
builder.Host.UseWolverine(opts =>
{
// Configurar RabbitMQ para eventos públicos
opts.UseRabbitMq("amqp://localhost")
.AutoProvision();
// Publicar eventos a RabbitMQ
opts.PublishMessage<IPublicEvent>()
.ToRabbitExchange("public-events");
});
// Registrar implementaciones de Cosmos
builder.Services.AddScoped<IEventStore, MartenEventStore>();
builder.Services.AddScoped<ICommandRouter, WolverineCommandRouter>();
builder.Services.AddScoped<IQueryRouter, WolverineQueryRouter>();
builder.Services.AddScoped<IEventSender, WolverineEventSender>();
builder.Services.AddScoped<IProjectionStore, MartenProjectionStore>();
var app = builder.Build();
app.Run();
Uso
Implementar Command Handlers con Wolverine
using Cosmos.EventSourcing.Abstractions.Commands;
using Wolverine.Attributes;
public record CreateOrder(string OrderId, string CustomerId);
// Los handlers son descubiertos automáticamente por Wolverine
public class CreateOrderHandler
{
private readonly IEventStore _eventStore;
public CreateOrderHandler(IEventStore eventStore)
{
_eventStore = eventStore;
}
public async Task Handle(CreateOrder command, CancellationToken ct)
{
var order = new Order(command.OrderId, command.CustomerId);
_eventStore.Save(order);
await _eventStore.SaveChangesAsync();
}
}
Ejecutar Comandos con el Router
public class OrderController : ControllerBase
{
private readonly ICommandRouter _commandRouter;
public OrderController(ICommandRouter commandRouter)
{
_commandRouter = commandRouter;
}
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderRequest request)
{
var command = new CreateOrder(Guid.NewGuid().ToString(), request.CustomerId);
await _commandRouter.InvokeAsync(command, HttpContext.RequestAborted);
return Ok(new { OrderId = command.OrderId });
}
}
Implementar Query Handlers
public record GetOrderById(string OrderId);
public class GetOrderByIdHandler
{
private readonly IProjectionStore _projectionStore;
public GetOrderByIdHandler(IProjectionStore projectionStore)
{
_projectionStore = projectionStore;
}
public async Task<OrderDto?> Handle(GetOrderById query, CancellationToken ct)
{
return await _projectionStore.GetByIdAsync<OrderDto>(query.OrderId, ct);
}
}
Publicar Eventos Públicos
using Cosmos.EventDriven.Abstractions;
public record OrderShipped(string OrderId, DateTime ShippedAt) : IPublicEvent;
public class ShipOrderHandler
{
private readonly IEventStore _eventStore;
private readonly IEventSender _eventSender;
public ShipOrderHandler(IEventStore eventStore, IEventSender eventSender)
{
_eventStore = eventStore;
_eventSender = eventSender;
}
public async Task Handle(ShipOrder command, CancellationToken ct)
{
var order = await _eventStore.GetAggregateRootAsync<Order>(command.OrderId, ct);
order?.Ship();
_eventStore.Save(order!);
await _eventStore.SaveChangesAsync();
// Publicar evento público a RabbitMQ
var publicEvent = new OrderShipped(command.OrderId, DateTime.UtcNow);
await _eventSender.PublishEventAsync(publicEvent);
}
}
Trabajar con Proyecciones
using Cosmos.EventSourcing.Linq.Extensions;
public class OrderQueryService
{
private readonly IQuerySession _querySession;
public OrderQueryService(IQuerySession querySession)
{
_querySession = querySession;
}
public async Task<IReadOnlyList<OrderDto>> GetCustomerOrdersAsync(
string customerId,
CancellationToken ct)
{
var orders = await _querySession
.Query<OrderDto>()
.Where(o => o.CustomerId == customerId)
.OrderByDescending(o => o.CreatedAt)
.ToListAsync(ct);
return orders;
}
}
Multi-Tenancy
Este paquete incluye soporte para multi-tenancy a través de Cosmos.MultiTenancy. Los routers de comandos y queries utilizan automáticamente el TenantResolver para ejecutar operaciones en el contexto del tenant correcto.
// El WolverineCommandRouter usa automáticamente el TenantId
await _commandRouter.InvokeAsync(command, ct);
// Internamente: messageBus.InvokeForTenantAsync(tenantId, command, ct)
Requisitos
- .NET 10.0 o superior
- PostgreSQL 12+ (para Marten)
- RabbitMQ (opcional, para eventos públicos)
Dependencias
- Marten (v8.16.1) - Event Store y Document DB
- WolverineFx (v5.4.0) - Mediación y mensajería
- WolverineFx.Marten (v5.4.0) - Integración Wolverine-Marten
- WolverineFx.RabbitMQ (v5.4.0) - Integración con RabbitMQ
- Cosmos.EventSourcing.Abstractions
- Cosmos.EventDriven.Abstractions
- Cosmos.MultiTenancy
Recursos
Licencia
Copyright © Cosmos. Todos los derechos reservados.
| 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
- Marten (>= 8.16.1)
- WolverineFx (>= 5.4.0)
- WolverineFx.Marten (>= 5.4.0)
- WolverineFx.RabbitMQ (>= 5.4.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.