グレインのライフサイクルの概要

Orleans グレインでは、順序づけられたアクティブ化と非アクティブ化には、監視可能なライフサイクル (Orleans のライフサイクルに関する記事を参照) を使用します。 これにより、グレイン ロジック、システム コンポーネント、アプリケーション ロジックは、グレインのアクティブ化と収集中に、順序付けされた方法で開始と停止を行うことができます。

ステージ

あらかじめ定義されたグレインのライフサイクル ステージは次のとおりです。

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: グレインのライフサイクルの最初のステージ。
  • SetupState: アクティブ化の前に、グレインの状態を設定します。 ステートフル グレインの場合、IStorage.RecordExiststrue のとき、IStorage<TState>.State がストレージから読み込まれるステージです。
  • Activate: Grain.OnActivateAsyncGrain.OnDeactivateAsync が呼び出されるステージ。
  • Last: グレインのライフサイクルの最終ステージ。

グレインのライフサイクルはグレインのアクティブ化中に使われますが、一部のエラー ケース (サイロのクラッシュなど) ではグレインが常に非アクティブ化されるとは限らないので、アプリケーションはグレインの非アクティブ化時に常に実行されるグレインのライフサイクルに依存しないようにする必要があります。

グレインのライフサイクルへの参加

アプリケーション ロジックは、次の 2 つの方法でグレインのライフサイクルに参加できます。

  • グレインはそのライフサイクルに参加できます。
  • コンポーネントは、グレインのアクティブ化コンテキスト (IGrainContext.ObservableLifecycle を参照) を介してライフサイクルにアクセスできます。
  • グレインはそのライフサイクルに参加できます。
  • コンポーネントは、グレインのアクティブ化コンテキスト (IGrainActivationContext.ObservableLifecycle を参照) を介してライフサイクルにアクセスできます。

グレインは常にそのライフサイクルに参加するので、参加のメソッドをオーバーライドすることでアプリケーション ロジックを導入できます。

参加の例

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

上記の例では、Grain<TGrainState>Grain.Participate メソッドをオーバーライドして、ライフサイクルの GrainLifecycleStage.SetupState ステージでその OnSetupState メソッドを呼び出すようにライフサイクルに指示します。

グレインの構築中に作成されたコンポーネントも、特別なグレイン ロジックを追加することなく、ライフサイクルに参加できます。 グレインのライフサイクル (IGrainContext.ObservableLifecycle) などのグレインのコンテキスト (IGrainContext) は、グレインの作成前に作成されるので、コンテナーによってグレインに挿入されたコンポーネントは、グレインのライフサイクルに参加できます。

グレインの構築中に作成されたコンポーネントも、特別なグレイン ロジックを追加することなく、ライフサイクルに参加できます。 グレインのライフサイクル (IGrainActivationContext.ObservableLifecycle) などのグレインのアクティブ化コンテキスト (IGrainActivationContext) は、グレインの作成前に作成されるので、コンテナーによってグレインに挿入されたコンポーネントは、グレインのライフサイクルに参加できます。

参加、作成、アクティブ化の例

次のコンポーネントは、そのファクトリ関数 Create(...) を使って作成されたときに、グレインのライフサイクルに参加します。 このロジックはコンポーネントのコンストラクターに含めることができますが、それにはコンポーネントが完全に構築される前にライフサイクルに追加されるリスクがあり、安全でない可能性があります。

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

ファクトリ関数 Create(...) を使ってサービス コンテナーに例のコンポーネントを登録すると、そのコンポーネントを依存関係として構築したグレインは、グレイン内に特別なロジックを含めずに、そのコンポーネントをライフサイクルに参加させることができるようになります。

コンテナーへのコンポーネントの登録

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

コンポーネントを依存関係として持つグレイン

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

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