Panoramica del ciclo di vita di Orleans

Alcuni comportamenti di Orleans sono sufficientemente complessi da richiedere un avvio e un arresto ordinati. Tra i componenti caratterizzati da tali comportamenti sono inclusi i grani, i silos e i client. Per gestire questa complessità, è stato introdotto un modello generale per il ciclo di vita dei componenti. Il modello consiste in un ciclo di vita osservabile, responsabile della segnalazione delle fasi di avvio e arresto di un componente, e in osservatori del ciclo di vita, responsabili dell'esecuzione di operazioni di avvio o arresto in fasi specifiche.

Per altre informazioni, vedere Ciclo di vita dei grani e Ciclo di vita dei silos.

Ciclo di vita osservabile

I componenti che richiedono un avvio e un arresto ordinati possono usare un ciclo di vita osservabile che consente ad altri componenti di osservare il ciclo di vita e ricevere una notifica quando viene raggiunta una fase durante l'avvio o l'arresto.

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

Nel momento in cui viene raggiunta una fase, la chiamata di sottoscrizione registra un osservatore per la notifica. Il nome dell'osservatore viene registrato solo a scopo di report. La fase indica il punto della sequenza di avvio/arresto in cui l'osservatore riceverà una notifica. Ogni fase del ciclo di vita è osservabile. Tutti gli osservatori ricevono una notifica quando la fase viene raggiunta all'avvio e all'arresto. Le fasi vengono avviate in ordine crescente e arrestate in ordine decrescente. L'osservatore può annullare la sottoscrizione eliminando l'oggetto eliminabile restituito.

Osservatore del ciclo di vita

I componenti che devono partecipare al ciclo di vita di un altro componente devono fornire hook per i loro comportamenti di avvio e arresto e sottoscrivere una fase specifica di un ciclo di vita osservabile.

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

Sia ILifecycleObserver.OnStart che ILifecycleObserver.OnStop vengono chiamati quando viene raggiunta la fase sottoscritta durante l'avvio o l'arresto.

Utilità

Per praticità, sono state create funzioni helper per modelli di utilizzo comuni del ciclo di vita.

Estensioni

Esistono funzioni di estensione per la sottoscrizione del ciclo di vita osservabile che non richiedono che il componente di sottoscrizione implementi ILifecycleObserver. Tali funzioni consentono invece ai componenti di passare una funzione lambda o membro da chiamare nelle fasi sottoscritte.

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

Funzioni di estensione simili consentono l'uso di argomenti di tipo generico al posto del nome dell'osservatore.

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

Partecipazione al ciclo di vita

Alcuni punti di estendibilità richiedono un modo per riconoscere quali componenti sono interessati a partecipare a un ciclo di vita. A questo scopo è stata introdotta un'interfaccia marcatore per i partecipanti al ciclo di vita. Altre informazioni sull'uso di questa interfaccia verranno illustrate durante l'esplorazione dei cicli di vita dei silos e dei grani.

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

Esempio

In base ai test del ciclo di vita eseguiti, di seguito è riportato un esempio di componente che partecipa a un ciclo di vita osservabile in più fasi del ciclo di vita.

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