Поделиться через


Orleans Обзор жизненного цикла

Некоторые Orleans поведения достаточно сложны, что им нужен упорядоченный запуск и завершение работы. Некоторые компоненты с таким поведением включают зерна, силосы и клиенты. Для решения этой проблемы представлен общий шаблон жизненного цикла компонентов. Этот шаблон состоит из наблюдаемого жизненного цикла, который отвечает за сигнал на этапах запуска и завершения работы компонента, а также наблюдатели жизненного цикла, ответственные за выполнение операций запуска или завершения работы на определенных этапах.

Дополнительные сведения см. в разделе "Жизненный цикл зерна" и жизненный цикл Silo.

Наблюдаемый жизненный цикл

Компоненты, требующие упорядоченного запуска и завершения работы, могут использовать наблюдаемый жизненный цикл, позволяющий другим компонентам наблюдать за жизненным циклом и получать уведомления о достижении этапа во время запуска или завершения работы.

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

Вызов подписки регистрирует наблюдателя для уведомления при достижении этапа при запуске или остановке. Имя наблюдателя предназначено для создания отчетов. Этап, указывающий, в какой момент в последовательности запуска и завершения работы наблюдатель будет уведомлен. Каждый этап жизненного цикла можно наблюдать. Все наблюдатели будут получать уведомления, когда этап достигается при запуске и остановке. Этапы начинаются в порядке возрастания и остановлены в порядке убывания. Наблюдатель может отменить подписку путем удаления возвращаемого удаленного объекта.

Наблюдатель жизненного цикла

Компоненты, которые должны участвовать в жизненном цикле другого компонента, должны предоставлять перехватчики для их поведения запуска и завершения работы и подписываться на определенный этап наблюдаемого жизненного цикла.

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

Оба ILifecycleObserver.OnStart и ILifecycleObserver.OnStop вызываются при достижении стадии, на которую подписана подписка во время запуска или завершения работы.

Служебные инструменты

Для удобства вспомогательные функции были созданы для распространенных шаблонов использования жизненного цикла.

Модули

Функции расширения существуют для подписки на наблюдаемый жизненный цикл, который не требует, чтобы компонент подписки реализовал ILifecycleObserver. Вместо этого эти компоненты позволяют компонентам передавать лямбда-лямбда-функции или функции-члены, которые будут вызываться на этапах подписки.

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

Аналогичные функции расширения позволяют использовать аргументы универсального типа вместо имени наблюдателя.

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

Участие в жизненном цикле

Некоторые точки расширяемости требуют способа распознавания того, какие компоненты заинтересованы в участии в жизненном цикле. Для этой цели был введен интерфейс маркера жизненного цикла. Дополнительные сведения о том, как это используется, будут рассмотрены при изучении жизненных циклов сило и зерна.

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

Пример

Из наших тестов жизненного цикла ниже приведен пример компонента, который участвует в наблюдаемом жизненном цикле на нескольких этапах жизненного цикла.

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