Przegląd cyklu życia ziarna

Orleans ziarna używają obserwowanego cyklu życia (zobacz Orleans cykl życia) do uporządkowanej aktywacji i dezaktywacji. Dzięki temu logika ziarna, składniki systemowe i logika aplikacji mogą być uruchamiane i zatrzymywane w uporządkowany sposób podczas aktywacji i zbierania ziarna.

Etapy

Wstępnie zdefiniowane etapy cyklu życia ziarna są następujące.

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

Cykl życia ziarna będzie używany podczas aktywacji ziarna, ponieważ ziarna nie zawsze są dezaktywowane podczas niektórych przypadków błędów (takich jak awarie silosu), aplikacje nie powinny polegać na cyklu życia ziarna zawsze wykonywane podczas dezaktywacji ziarna.

Udział w cyklu życia ziarna

Logika aplikacji może uczestniczyć w cyklu życia ziarna na dwa sposoby:

  • Ziarno może uczestniczyć w jego cyklu życia.
  • Składniki mogą uzyskiwać dostęp do cyklu życia za pośrednictwem kontekstu aktywacji ziarna (zobacz IGrainContext.ObservableLifecycle).

Ziarno zawsze uczestniczy w jego cyklu życia, więc logika aplikacji może być wprowadzana przez zastąpienie metody uczestniczyć.

Przykładowe uczestnictwo

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

W powyższym przykładzie Grain<TGrainState> zastępuje metodę Grain.Participate , aby poinformować cykl życia o wywołaniu jej OnSetupState metody na GrainLifecycleStage.SetupState etapie cyklu życia.

Składniki tworzone podczas budowy ziarna mogą również brać udział w cyklu życia, bez dodawania specjalnej logiki ziarna. Ponieważ kontekst ziarna (IGrainContext), w tym cykl życia ziarna (IGrainContext.ObservableLifecycle), jest tworzony przed utworzeniem ziarna, każdy składnik wstrzykiwany do ziarna przez kontener może uczestniczyć w cyklu życia ziarna.

Składniki tworzone podczas budowy ziarna mogą również brać udział w cyklu życia, bez dodawania specjalnej logiki ziarna. Ponieważ kontekst aktywacji ziarna (IGrainActivationContext), w tym cykl życia ziarna (IGrainActivationContext.ObservableLifecycle), jest tworzony przed utworzeniem ziarna, każdy składnik wstrzykiwany do ziarna przez kontener może uczestniczyć w cyklu życia ziarna.

Przykładowe uczestnictwo, tworzenie i aktywacja

Poniższy składnik uczestniczy w cyklu życia ziarna podczas tworzenia przy użyciu funkcji Create(...)fabryki . Ta logika może istnieć w konstruktorze składnika, ale wiąże się to z ryzykiem dodania składnika do cyklu życia przed jego w pełni skonstruowaniem, co może nie być bezpieczne.

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

Rejestrując przykładowy składnik w kontenerze usługi przy użyciu funkcji fabryki, każde ziarno skonstruowane ze składnikiem jako zależność będzie miało składnik biorący udział w jego Create(...) cyklu życia bez żadnej specjalnej logiki w ziarnie.

Rejestrowanie składnika w kontenerze

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

Ziarno ze składnikiem jako zależność

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

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