Vue d’ensemble du cycle de vie des grains

Les grains Orleans utilisent un cycle de vie observable (consultez Cycle de vie Orleans) pour une activation et une désactivation ordonnées. Cela permet de démarrer et d’arrêter de manière ordonnée la logique de grain, les composants système et la logique d’application pendant l’activation et la collecte des grains.

Étapes

Les étapes du cycle de vie prédéfini des grains sont les suivantes.

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

Bien que le cycle de vie des grains soit utilisé pendant l’activation des grains, sachant que les grains ne sont pas toujours désactivés dans certains cas d’erreur (tels que les blocages de silo), les applications ne doivent pas se fier au cycle de vie des grains toujours exécutés pendant les désactivations de grains.

Participation au cycle de vie des grains

La logique d’application peut participer au cycle de vie d’un grain de deux façons :

  • Le grain peut participer à son cycle de vie.
  • Les composants peuvent accéder au cycle de vie via le contexte d’activation du grain (consultez IGrainContext.ObservableLifecycle).

Un grain participe toujours à son cycle de vie. Ainsi, la logique d’application peut être introduite en remplaçant la méthode participate.

Exemple de participation

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

Dans l’exemple ci-dessus, Grain<TGrainState> remplace la méthode Grain.Participate pour demander au cycle de vie d’appeler sa méthode OnSetupState dans le cadre de l’étape GrainLifecycleStage.SetupState du cycle de vie.

Les composants créés durant la construction d’un grain peuvent aussi prendre part au cycle de vie, sans l’ajout d’aucune logique de grain spéciale. Étant donné que le contexte du grain (IGrainContext), y compris le cycle de vie du grain (IGrainContext.ObservableLifecycle), est créé avant la création du grain, tout composant injecté dans le grain par le conteneur peut participer au cycle de vie du grain.

Les composants créés durant la construction d’un grain peuvent aussi prendre part au cycle de vie, sans l’ajout d’aucune logique de grain spéciale. Étant donné que le contexte d’activation du grain (IGrainActivationContext), y compris le cycle de vie du grain (IGrainActivationContext.ObservableLifecycle), est créé avant la création du grain, tout composant injecté dans le grain par le conteneur peut participer au cycle de vie du grain.

Exemple de participation, de création et d’activation

Le composant suivant participe au cycle de vie du grain quand il est créé à l’aide de sa fonction d’usine Create(...). Cette logique peut exister dans le constructeur du composant, mais le risque est que le composant soit ajouté au cycle de vie avant qu’il soit entièrement construit, ce qui n’est pas sûr.

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

En inscrivant l’exemple de composant dans le conteneur de service à l’aide de sa fonction d’usine Create(...), tout grain construit avec le composant comme dépendance verra le composant prendre part à son cycle de vie sans logique spéciale dans le grain.

Inscrire le composant dans le conteneur

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

Grain avec le composant comme dépendance

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

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