Middleware

Введение

Pipeline TeleFlow реализован как цепочка IHandler<T>. Каждое звено этой цепочки является middleware.

Middleware получает объект контекста, выполняет обработку и передаёт управление следующему звену.

Примечание

Большинство пользовательских расширений Pipeline реализуются именно через добавление собственных middleware.

—

Типы middleware

В Pipeline можно выделить два типа middleware.

Контекстные middleware

Работают с уже существующим типом контекста и не изменяют его тип.

Например:

  • IHandlerMiddleware<UpdateContext>

  • IHandlerMiddleware<SessionContext>

  • IHandlerMiddleware<CommandResultContext>

Это естественная точка расширения Pipeline. Именно здесь обычно добавляется пользовательская логика.

—

Переходные middleware

Преобразуют один тип контекста в другой.

Например:

  • Update → UpdateContext

  • UpdateContext → SessionContext

  • SessionContext → CommandResultContext

Эти middleware формируют структуру Pipeline.

Примечание

В большинстве случаев переходные middleware не изменяются. При необходимости их можно переопределить и встроить в собственную конфигурацию Pipeline.

—

Интерпретаторы

Middleware, работающие с CommandResultContext, образуют цепочку интерпретаторов.

Именно они определяют, как обрабатывается результат выполнения команды.

В конце цепочки интерпретаторов всегда находится DefaultCommandInterpreter:

public class DefaultCommandInterpreter : IHandler<CommandResultContext>
{
    private readonly IChatSessionStore _sessionStore;

    public async Task Handle(CommandResultContext args)
    {
        var chatId = args.GetService<IChatIdProvider>().GetChatId();

        await _sessionStore.RemoveAsync(chatId);

        throw new Exception(
            "No command interpreter matched the command result of type "
            + args.CommandResult.GetType().FullName);
    }

    public DefaultCommandInterpreter(IChatSessionStore sessionStore)
    {
        _sessionStore = sessionStore;
    }
}

Этот обработчик выполняется, если ни один интерпретатор не обработал CommandResult.

—

Порядок выполнения

Middleware выполняются строго в порядке их регистрации.

Каждый middleware:

  1. Получает контекст.

  2. Выполняет свою логику.

  3. Передаёт управление через Next.Handle(...).

Если управление не передаётся дальше, цепочка на текущем этапе завершается.

—

Когда писать собственный middleware

Собственный middleware имеет смысл добавлять, если требуется:

  • глобальное логирование;

  • централизованная обработка ошибок;

  • изменение инфраструктурного поведения;

  • дополнительная обработка контекста до или после команды.

Если логика относится к конкретной команде, следует использовать Interceptor.