Visão geral do ciclo de vida de grãos

As granularidades do Orleans usam um ciclo de vida observável (confira Ciclo de vida do Orleans) para ativação e desativação ordenadas. Isso permite que a lógica de grãos, os componentes do sistema e a lógica do aplicativo sejam iniciados e interrompidos de maneira ordenada durante a ativação e a coleta de grãos.

Estágios

Veja a seguir os estágios predefinidos do ciclo de vida de grãos.

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;
}

Embora o ciclo de vida do grão seja usado durante a ativação do grão, os grãos nem sempre são desativados durante alguns casos de erro (como falhas de silo) e, portanto, os aplicativos não devem confiar que o ciclo de vida do grão sempre será executado durante as desativações de grão.

Participação no ciclo de vida do grão

A lógica do aplicativo pode participar do ciclo de vida de um grão de duas maneiras:

  • O grão pode participar do ciclo de vida.
  • Os componentes podem acessar o ciclo de vida por meio do contexto de ativação do grão (confira IGrainContext.ObservableLifecycle).

Um grão sempre participa do ciclo de vida, portanto, a lógica do aplicativo pode ser introduzida substituindo o método de participação.

Participação de exemplo

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

No exemplo acima, Grain<TGrainState> substitui o método Grain.Participate para informar ao ciclo de vida que ele deve chamar o método OnSetupState durante o estágio GrainLifecycleStage.SetupState do ciclo de vida.

Os componentes criados durante a construção de um grão também podem participar do ciclo de vida, sem a adição de nenhuma lógica de grão especial. Como o contexto do grão (IGrainContext), incluindo o ciclo de vida do grão (IGrainContext.ObservableLifecycle), é criado antes da criação do grão, qualquer componente injetado no grão pelo contêiner pode participar do ciclo de vida do grão.

Os componentes criados durante a construção de um grão também podem participar do ciclo de vida, sem a adição de nenhuma lógica de grão especial. Como o contexto de ativação do grão (IGrainActivationContext), incluindo o ciclo de vida do grão (IGrainActivationContext.ObservableLifecycle), é criado antes da criação do grão, qualquer componente injetado no grão pelo contêiner pode participar do ciclo de vida do grão.

Participação, criação e ativação de exemplo

O componente a seguir participa do ciclo de vida do grão quando é criado usando a função de fábrica Create(...). Essa lógica pode existir no construtor do componente, mas isso acarreta no risco de o componente ser adicionado ao ciclo de vida antes de estar totalmente construído, o que pode não 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
    }
}

Ao registrar o exemplo de componente no contêiner de serviço usando a função de fábrica Create(...), qualquer grão construído tendo o componente como uma dependência terá a participação dele no ciclo de vida sem nenhuma lógica especial no grão.

Registrar componentes no contêiner

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

Grão com um componente como uma dependência

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

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