Übersicht über den Orleans-Lebenszyklus

Einige Orleans-Verhalten sind so komplex, dass ein geordnetes Starten und Herunterfahren erforderlich ist. Komponenten, die ein solches Verhalten aufweisen, sind u. a. Grains, Silos und Clients. Um dieses Problem zu beheben, wurde ein allgemeines Komponentenlebenszyklusmuster eingeführt. Dieses Muster besteht aus einem beobachtbaren Lebenszyklus und aus Lebenszyklusbeobachtern. Der Lebenszyklus signalisiert die Phasen zum Starten und Herunterfahren einer Komponente. Die Lebenszyklusbeobachter führen die Vorgänge zum Starten oder Herunterfahren in bestimmten Phasen aus.

Weitere Informationen finden Sie unter Grain-Lebenszyklus und Lebenszyklus des Silos.

Beobachtbarer Lebenszyklus

Komponenten, für die ein geordnetes Starten und Herunterfahren erforderlich ist, können einen beobachtbaren Lebenszyklus verwenden. Dies ermöglicht es anderen Komponenten, den Lebenszyklus zu beobachten und eine Benachrichtigung zu erhalten, wenn während des Startens oder Herunterfahrens eine Phase erreicht wird.

public interface ILifecycleObservable
{
    IDisposable Subscribe(
        string observerName,
        int stage,
        ILifecycleObserver observer);
}

Der subscribe-Aufruf registriert einen Beobachter und sendet eine Benachrichtigung, wenn beim Starten oder Beenden eine Phase erreicht wird. Der Name des Beobachters dient zu Berichtszwecken. Die Phase gibt an, an welcher Stelle in der Sequenz zum Starten/Herunterfahren der Beobachter benachrichtigt wird. Jede Phase des Lebenszyklus kann beobachtet werden. Alle Beobachter werden benachrichtigt, wenn die Phase beim Starten und Beenden erreicht wird. Phasen werden in aufsteigender Reihenfolge gestartet und in absteigender Reihenfolge beendet. Der Beobachter kann die Benachrichtigung abbestellen, indem das zurückgegebene verwerfbare Objekt verworfen wird.

Lebenszyklusbeobachter

Komponenten, die am Lebenszyklus einer anderen Komponente beteiligt sein müssen, müssen Hooks für ihr Verhalten zum Starten und Herunterfahren bereitstellen und eine bestimmte Phase eines beobachtbaren Lebenszyklus abonnieren.

public interface ILifecycleObserver
{
    Task OnStart(CancellationToken ct);
    Task OnStop(CancellationToken ct);
}

Sowohl ILifecycleObserver.OnStart als auch ILifecycleObserver.OnStop werden aufgerufen, wenn die abonnierte Phase während des Startens/Herunterfahrens erreicht wird.

Versorgungsunternehmen

Der Einfachheit halber wurden Hilfsfunktionen für allgemeine Lebenszyklusnutzungsmuster erstellt.

Erweiterungen

Es sind Erweiterungsfunktionen für das Abonnieren von beobachtbaren Lebenszyklen vorhanden, bei denen ILifecycleObserver nicht von der abonnierenden Komponente implementiert werden muss. Stattdessen ermöglichen diese Lebenszyklen die Übergabe von Komponenten in Lambda- oder Memberfunktionen, die in den abonnierten Phasen aufgerufen werden.

IDisposable Subscribe(
    this ILifecycleObservable observable,
    string observerName,
    int stage,
    Func<CancellationToken, Task> onStart,
    Func<CancellationToken, Task> onStop);

IDisposable Subscribe(
    this ILifecycleObservable observable,
    string observerName,
    int stage,
    Func<CancellationToken, Task> onStart);

Ähnliche Erweiterungsfunktionen ermöglichen die Verwendung generischer Typargumente anstelle des Beobachternamens.

IDisposable Subscribe<TObserver>(
    this ILifecycleObservable observable,
    int stage,
    Func<CancellationToken, Task> onStart,
    Func<CancellationToken, Task> onStop);

IDisposable Subscribe<TObserver>(
    this ILifecycleObservable observable,
    int stage,
    Func<CancellationToken, Task> onStart);

Teilnahme am Lebenszyklus

Einige Erweiterbarkeitspunkte benötigen eine Möglichkeit, um zu erkennen, welche Komponenten an einem Lebenszyklus teilnehmen möchten. Zu diesem Zweck wurde eine Markerschnittstelle für Lebenszyklusteilnehmer eingeführt. Die Verwendung dieser Schnittstelle wird bei der Untersuchung von Silo- und Grain-Lebenszyklen detaillierter behandelt.

public interface ILifecycleParticipant<TLifecycleObservable>
    where TLifecycleObservable : ILifecycleObservable
{
    void Participate(TLifecycleObservable lifecycle);
}

Beispiel

Im Folgenden sehen Sie ein Beispiel aus unseren Lebenszyklustests, in dem eine Komponente in mehreren Phasen des Lebenszyklus an einem beobachtbaren Lebenszyklus teilnimmt.

enum TestStages
{
    Down,
    Initialize,
    Configure,
    Run,
};

class MultiStageObserver : ILifecycleParticipant<ILifecycleObservable>
{
    public Dictionary<TestStages,bool> Started { get; } = new();
    public Dictionary<TestStages, bool> Stopped { get; } = new();

    private Task OnStartStage(TestStages stage)
    {
        Started[stage] = true;

        return Task.CompletedTask;
    }

    private Task OnStopStage(TestStages stage)
    {
        Stopped[stage] = true;

        return Task.CompletedTask;
    }

    public void Participate(ILifecycleObservable lifecycle)
    {
        lifecycle.Subscribe<MultiStageObserver>(
            (int)TestStages.Down,
            _ => OnStartStage(TestStages.Down),
            _ => OnStopStage(TestStages.Down));

        lifecycle.Subscribe<MultiStageObserver>(
            (int)TestStages.Initialize,
            _ => OnStartStage(TestStages.Initialize),
            _ => OnStopStage(TestStages.Initialize));

        lifecycle.Subscribe<MultiStageObserver>(
            (int)TestStages.Configure,
            _ => OnStartStage(TestStages.Configure),
            _ => OnStopStage(TestStages.Configure));

        lifecycle.Subscribe<MultiStageObserver>(
            (int)TestStages.Run,
            _ => OnStartStage(TestStages.Run),
            _ => OnStopStage(TestStages.Run));
    }
}