Información general sobre el ciclo de vida del grano

Los granos de Orleans usan un ciclo de vida observable (consulte Ciclo de vida de Orleans) para la activación y desactivación ordenadas. Esto permite que la lógica de grano, los componentes del sistema y la lógica de aplicación se inicien y detengan de forma ordenada durante la activación y colección de granos.

Fases

Las fases predefinidas del ciclo de vida del grano son las siguientes.

public static class GrainLifecycleStage
{
    public const int First = int.MinValue;
    public const int SetupState = 1_000;
    public const int Activate = 2_000;
    public const int Last = int.MaxValue;
}

Aunque el ciclo de vida del grano se usará durante la activación de granos, dado que los granos, en algunos casos de error, no se desactivan siempre (como bloqueos de silos), las aplicaciones no deben depender de que el ciclo de vida del grano se ejecute siempre durante las desactivaciones de granos.

Participación del ciclo de vida del grano

La lógica de la aplicación puede participar en el ciclo de vida de un grano de dos formas:

  • El grano puede participar en su ciclo de vida.
  • Los componentes pueden acceder al ciclo de vida a través del contexto de activación del grano (consulte IGrainContext.ObservableLifecycle).

Un grano siempre participa en su ciclo de vida, por lo que la lógica de la aplicación se puede introducir mediante la invalidación del método de participación.

Ejemplo de participación

public override void Participate(IGrainLifecycle lifecycle)
{
    base.Participate(lifecycle);
    lifecycle.Subscribe(
        this.GetType().FullName,
        GrainLifecycleStage.SetupState,
        OnSetupState);
}

En el ejemplo anterior, Grain<TGrainState> invalida el método Grain.Participate para indicar al ciclo de vida que llame al método OnSetupState durante la fase GrainLifecycleStage.SetupState del ciclo de vida.

Los componentes que se crean durante la construcción de un grano también pueden participar en el ciclo de vida, sin agregar ninguna lógica de grano especial. Dado que el contexto del grano (IGrainContext), incluido el ciclo de vida del grano (IGrainContext.ObservableLifecycle), se crea antes que el grano, cualquier componente que el contenedor inserte en el grano puede participar en el ciclo de vida del grano.

Los componentes que se crean durante la construcción de un grano también pueden participar en el ciclo de vida, sin agregar ninguna lógica de grano especial. Dado que el contexto de activación de grano (IGrainActivationContext), incluido el ciclo de vida del grano (IGrainActivationContext.ObservableLifecycle), se crea antes que el grano, cualquier componente que el contenedor inserte en el grano puede participar en el ciclo de vida del grano.

Ejemplo de participación, creación y activación

El siguiente componente participa en el ciclo de vida del grano cuando se crea con la función de generador Create(...). Esta lógica puede existir en el constructor del componente, pero corre el riesgo de que el componente se agregue al ciclo de vida antes de que esté construido por completo, lo que puede no ser seguro.

public class MyComponent : ILifecycleParticipant<IGrainLifecycle>
{
    public static MyComponent Create(IGrainContext context)
    {
        var component = new MyComponent();
        component.Participate(context.ObservableLifecycle);
        return component;
    }

    public void Participate(IGrainLifecycle lifecycle)
    {
        lifecycle.Subscribe<MyComponent>(GrainLifecycleStage.Activate, OnActivate);
    }

    private Task OnActivate(CancellationToken ct)
    {
        // Do stuff
    }
}
public class MyComponent : ILifecycleParticipant<IGrainLifecycle>
{
    public static MyComponent Create(IGrainActivationContext context)
    {
        var component = new MyComponent();
        component.Participate(context.ObservableLifecycle);
        return component;
    }

    public void Participate(IGrainLifecycle lifecycle)
    {
        lifecycle.Subscribe<MyComponent>(GrainLifecycleStage.Activate, OnActivate);
    }

    private Task OnActivate(CancellationToken ct)
    {
        // Do stuff
    }
}

Al registrar el componente de ejemplo en el contenedor de servicio con la función de generador Create(...), el componente de cualquier grano que se haya construido con el componente como dependencia participará en el ciclo de vida sin ninguna lógica especial en el grano.

Registro de componentes en el contenedor

services.AddTransient<MyComponent>(sp =>
    MyComponent.Create(sp.GetRequiredService<IGrainContext>());
services.AddTransient<MyComponent>(sp =>
    MyComponent.Create(sp.GetRequiredService<IGrainActivationContext>());

Grano con el componente como una dependencia

public class MyGrain : Grain, IMyGrain
{
    private readonly MyComponent _component;

    public MyGrain(MyComponent component)
    {
        _component = component;
    }
}