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;
}
First
: primeira fase no ciclo de vida do grão.SetupState
: fase de granularidade de instalação, antes da ativação. Para grãos com estado, essa é a fase em que IStorage<TState>.State é carregado do armazenamento, quando IStorage.RecordExists étrue
.Activate
: fase em que Grain.OnActivateAsync e Grain.OnDeactivateAsync são chamados.Last
: última fase no ciclo de vida do grão.
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).
- 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 IGrainActivationContext.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;
}
}