En esta clase aprenderemos cómo usar Event Sourcing en Orleans para registrar cambios en el estado de los Granos y reconstruir su estado desde un historial de eventos.
Objetivos de la Clase
- Comprender qué es Event Sourcing y cómo Orleans lo implementa.
- Implementar Granos basados en eventos en Orleans.
- Configurar almacenamiento de eventos en Orleans.
- Probar la recuperación del estado de un Grano a partir de su historial de eventos.
¿Qué es Event Sourcing?
Event Sourcing es un patrón en el que el estado de un objeto no se guarda directamente, sino que se registra una secuencia de eventos que pueden usarse para reconstruir el estado en cualquier momento.
Beneficios de Event Sourcing en Orleans
- Historial completo de cambios, útil para auditoría y depuración.
- Facilidad para replicación y recuperación del estado.
- Desacoplamiento de la persistencia, mejorando escalabilidad.
Ejemplo de uso
- Gestión de pedidos: Cada cambio en un pedido se registra como un evento.
- Control de acceso: Cada inicio de sesión es un evento auditable.
- Sistemas financieros: Historial de transacciones para reconstruir saldos.
Implementar Event Sourced Grains en Orleans
1. Instalar Dependencias
Ejecuta en OrleansDemo:
dotnet add package Orleans.EventSourcing
dotnet add package Microsoft.Orleans.Persistence.AdoNet
2. Configurar Almacenamiento de Eventos en Program.cs
Edita Program.cs
en OrleansDemo para habilitar el almacenamiento de eventos en memoria:
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddMemoryGrainStorage("eventStore");
});
Para usar SQL Server como almacenamiento de eventos, agrega:
siloBuilder.AddAdoNetGrainStorage("eventStore", options =>
{
options.Invariant = "System.Data.SqlClient";
options.ConnectionString = "Server=localhost;Database=OrleansDB;User Id=sa;Password=YourPassword;";
});
Implementar un Grano Basado en Eventos
1. Definir la Interfaz del Grano
Crea IPedidoGrain.cs
en Granos:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Orleans;
public interface IPedidoGrain : IGrainWithStringKey
{
Task AgregarItem(string item, int cantidad);
Task ConfirmarPedido();
Task<List<string>> ObtenerHistorialEventos();
}
2. Definir la Clase de Eventos
Crea EventosPedido.cs
en Granos:
using System;
using Orleans.EventSourcing;
[GenerateSerializer]
public class PedidoCreado : JournaledGrainEvent {}
[GenerateSerializer]
public class ItemAgregado : JournaledGrainEvent
{
[Id(0)] public string Item { get; set; }
[Id(1)] public int Cantidad { get; set; }
}
[GenerateSerializer]
public class PedidoConfirmado : JournaledGrainEvent {}
3. Implementar el Grano Basado en Eventos
Crea PedidoGrain.cs
en Granos:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Orleans;
using Orleans.EventSourcing;
public class PedidoGrain : JournaledGrain<PedidoState>, IPedidoGrain
{
public async Task AgregarItem(string item, int cantidad)
{
var evento = new ItemAgregado { Item = item, Cantidad = cantidad };
RaiseEvent(evento);
await ConfirmEvents();
}
public async Task ConfirmarPedido()
{
var evento = new PedidoConfirmado();
RaiseEvent(evento);
await ConfirmEvents();
}
public Task<List<string>> ObtenerHistorialEventos()
{
return Task.FromResult(this.RetrievedEvents.Select(e => e.GetType().Name).ToList());
}
}
[GenerateSerializer]
public class PedidoState
{
[Id(0)] public List<string> Items { get; set; } = new List<string>();
}
Explicación del Código
RaiseEvent(evento)
: Agrega un evento al historial del Grano.ConfirmEvents()
: Persiste los eventos en el almacenamiento.RetrievedEvents
: Permite recuperar todos los eventos pasados.
Probar Event Sourcing en Orleans
1. Ejecutar el Silo Orleans
dotnet run
2. Probar con un Cliente Orleans
Edita Program.cs
en OrleansClient y agrega:
var cliente = new ClientBuilder()
.UseLocalhostClustering()
.Build();
await cliente.Connect();
var pedido = cliente.GetGrain<IPedidoGrain>("pedido123");
await pedido.AgregarItem("Laptop", 1);
await pedido.AgregarItem("Mouse", 2);
await pedido.ConfirmarPedido();
var historial = await pedido.ObtenerHistorialEventos();
Console.WriteLine("Historial de eventos:");
foreach (var evento in historial)
{
Console.WriteLine(evento);
}
Salida esperada
Historial de eventos:
ItemAgregado
ItemAgregado
PedidoConfirmado
Si se reinicia el Silo, Orleans reconstruirá el estado del Grano a partir de los eventos almacenados.
Cuestionario de Autoevaluación
- ¿Qué es Event Sourcing y cómo se diferencia de la persistencia tradicional?
- ¿Cómo Orleans almacena y recupera eventos en un Grano basado en eventos?
- ¿Qué hace
RaiseEvent()
en un Event Sourced Grain? - ¿Qué ventajas tiene usar Event Sourcing en un sistema distribuido?
- ¿Qué sucede si un Grano basado en eventos se desactiva y se reactiva?
Resumen de la Clase
- Event Sourcing en Orleans permite almacenar cambios como una secuencia de eventos en lugar de estados finales.
- Implementamos un Grano de Pedidos que registra cambios en su historial de eventos.
- Orleans puede reconstruir el estado de un Grano desde su historial de eventos.
- Probamos el sistema y verificamos que el estado del Grano se mantiene incluso después de reiniciar el Silo.
Próxima Clase: Actualización de Granos
En la siguiente clase, aprenderemos cómo actualizar Granos Orleans sin perder datos ni interrumpir el servicio, asegurando compatibilidad con versiones anteriores.