En esta clase, aprenderemos cómo persistir datos en Orleans, permitiendo que los Granos recuerden información después de reiniciarse.
Objetivos de la Clase
- Comprender cómo Orleans maneja el almacenamiento de estado.
- Aprender a usar
IPersistentState<T>
para almacenar datos en un Grano. - Configurar almacenamiento en memoria en Orleans.
- Probar la persistencia de datos después de reiniciar el sistema.
¿Cómo maneja Orleans el almacenamiento de estado?
Por defecto, los Granos en Orleans no recuerdan su estado cuando se desactivan. Sin embargo, podemos persistir su estado en una base de datos o almacenamiento en memoria utilizando IPersistentState<T>
.
Cuando un Grano con almacenamiento persistente se reactiva, Orleans recupera su estado automáticamente, sin que el desarrollador tenga que preocuparse por cargar datos manualmente.
Ejemplo de uso en aplicaciones reales
- Un sistema de pedidos donde cada pedido es un Grano y mantiene su estado hasta que se completa.
- Un juego en línea donde el progreso de los jugadores se guarda y recupera al reconectar.
- Un sistema de gestión de usuarios que almacena nombres y preferencias de los clientes.
Implementar almacenamiento persistente en Orleans
Para demostrar cómo un Grano puede almacenar su estado, crearemos un Grano de usuario que guardará y recuperará su nombre.
1. Definir la interfaz del Grano
Crea un archivo IUsuarioGrain.cs
en la carpeta Granos:
using System.Threading.Tasks;
using Orleans;
public interface IUsuarioGrain : IGrainWithStringKey
{
Task SetNombre(string nombre);
Task<string> GetNombre();
}
2. Implementar el Grano con almacenamiento persistente
Crea un archivo UsuarioGrain.cs
en la carpeta Granos:
using System.Threading.Tasks;
using Orleans;
using Orleans.Runtime;
public class UsuarioGrain : Grain, IUsuarioGrain
{
private readonly IPersistentState<UsuarioState> _state;
public UsuarioGrain([PersistentState("usuario", "memoryStore")] IPersistentState<UsuarioState> state)
{
_state = state;
}
public async Task SetNombre(string nombre)
{
_state.State.Nombre = nombre;
await _state.WriteStateAsync(); // Guarda en la base de datos
}
public Task<string> GetNombre()
{
return Task.FromResult(_state.State.Nombre);
}
}
public class UsuarioState
{
public string Nombre { get; set; } = "Desconocido";
}
Explicación del código
IPersistentState<T>
almacena el estado del Grano en una base de datos o almacenamiento en memoria.SetNombre(string nombre)
: Guarda el nombre del usuario.GetNombre()
: Recupera el nombre almacenado.WriteStateAsync()
: Guarda el estado en el almacenamiento configurado.
Configurar almacenamiento en Orleans
Para que Orleans pueda almacenar datos, es necesario habilitar el almacenamiento persistente en el Silo.
Edita Program.cs
en el proyecto OrleansDemo y agrega la configuración:
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Orleans;
using Orleans.Hosting;
class Program
{
static async Task Main(string[] args)
{
var host = Host.CreateDefaultBuilder()
.UseOrleans(builder =>
{
builder.UseLocalhostClustering();
builder.AddMemoryGrainStorage("memoryStore"); // Agrega almacenamiento en memoria
})
.Build();
await host.RunAsync();
}
}
Explicación del código
.AddMemoryGrainStorage("memoryStore")
: Configura Orleans para almacenar datos en memoria."memoryStore"
es el nombre del almacenamiento y debe coincidir con el usado enUsuarioGrain.cs
.
Probar la persistencia de datos
Para verificar que la persistencia funciona, modificaremos el Cliente Orleans para almacenar y recuperar datos.
Edita Program.cs
en OrleansClient:
using System;
using System.Threading.Tasks;
using Orleans;
using Orleans.Hosting;
class Program
{
static async Task Main(string[] args)
{
var client = new ClientBuilder()
.UseLocalhostClustering()
.Build();
await client.Connect();
Console.WriteLine("Cliente conectado a Orleans.");
var usuarioGrain = client.GetGrain<IUsuarioGrain>("usuario1");
Console.WriteLine("Escribe un nombre:");
string nombre = Console.ReadLine();
await usuarioGrain.SetNombre(nombre);
Console.WriteLine("Nombre guardado.");
string nombreGuardado = await usuarioGrain.GetNombre();
Console.WriteLine($"Nombre almacenado: {nombreGuardado}");
}
}
Explicación del código
- Se solicita al usuario que ingrese un nombre.
- El nombre se guarda en el Grano con
SetNombre()
. - Luego se recupera con
GetNombre()
y se muestra en consola.
Ejecutar la aplicación y probar la persistencia
Paso 1: Iniciar el Silo
- Ejecuta el proyecto OrleansDemo para iniciar el Silo.
Paso 2: Ejecutar el Cliente
- Ejecuta OrleansClient.
- Escribe un nombre cuando se te pida.
- El cliente mostrará el nombre guardado.
Ejemplo de salida en consola:
Cliente conectado a Orleans.
Escribe un nombre:
Carlos
Nombre guardado.
Nombre almacenado: Carlos
Paso 3: Probar la persistencia
- Detén el Silo y el Cliente.
- Reinicia solo el Silo y el Cliente.
- El Cliente debe recuperar el nombre guardado previamente.
Si el nombre permanece después del reinicio, la persistencia funciona correctamente.
Cuestionario de Autoevaluación
- ¿Qué es el almacenamiento persistente en Orleans y por qué es importante?
- ¿Cómo se usa
IPersistentState<T>
dentro de un Grano? - ¿Qué sucede si un Grano se desactiva sin persistencia habilitada?
- ¿Cómo se configura el almacenamiento en memoria en Orleans?
- ¿En qué situaciones es útil la persistencia en Orleans?
Resumen de la Clase
- Orleans permite almacenar el estado de los Granos mediante
IPersistentState<T>
. - Usamos almacenamiento en memoria para probar la persistencia.
- Un Silo maneja el almacenamiento y un Cliente interactúa con los Granos.
- Probamos que los datos se mantienen después de reiniciar el sistema.
Próxima Clase: Timers y Reminders
En la siguiente clase, aprenderemos cómo programar tareas automáticas en Orleans mediante Timers y Reminders.