Writing Custom Middleware

Введение

В большинстве случаев стандартного Pipeline достаточно. Однако TeleFlow позволяет добавлять собственные middleware в существующую цепочку обработки.

В этом разделе рассматривается создание контекстного middleware. Переходные middleware относятся к расширенной конфигурации и рассматриваются как advanced-сценарий.

Когда нужен собственный middleware

Middleware применяется глобально — он выполняется для всех апдейтов на соответствующей стадии Pipeline.

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

  • добавить поддержку нового типа CommandResult и создать интерпретатор;

  • логировать входящие апдейты;

  • реализовать глобальную обработку ошибок;

  • измерять время выполнения;

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

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

Создание middleware

Для создания собственного middleware необходимо реализовать интерфейс IHandlerMiddleware<T>.

Пример middleware, работающего на стадии UpdateContext:

using Microsoft.Extensions.Logging;
using TeleFlow.Abstractions.Engine.Pipeline;
using TeleFlow.Abstractions.Engine.Pipeline.Contexts;

public class LoggingMiddleware : IHandlerMiddleware<UpdateContext>
{
    private readonly ILogger<LoggingMiddleware> _logger;

    public IHandler<UpdateContext> Next { get; }

    public LoggingMiddleware(
        ILogger<LoggingMiddleware> logger,
        IHandler<UpdateContext> next)
    {
        _logger = logger;
        Next = next;
    }

    public async Task Handle(UpdateContext context)
    {
        if (context.Update.Message?.Text is not null)
        {
            var chatId = context.Update.Message.Chat.Id;
            var text   = context.Update.Message.Text;

            _logger.LogInformation(
                "New message in chat {ChatId}: {Message}",
                chatId,
                text);
        }

        await Next.Handle(context);
    }
}

Этот middleware будет логировать все входящие текстовые сообщения на стадии UpdateContext.

Важно

Передача управления следующему обработчику выполняется через Next.Handle(context).

Если не вызвать Next, дальнейшая обработка Pipeline будет остановлена.

Регистрация middleware

Чтобы подключить middleware, его необходимо добавить в конфигурацию TeleFlow.

Пример:

var builder = Host.CreateDefaultBuilder();

builder
    .ConfigureServices(services =>
        services.AddTeleFlowPolling(
            botToken: token,
            teleFlow: options =>
            {
                options.ConfigureMiddlewarePipeline(middleware =>
                {
                    middleware
                        .WithUpdateContextMiddleware<LoggingMiddleware>();
                });
            }));

await builder.Build().RunAsync();

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

Результат работы

После регистрации middleware при каждом входящем сообщении в журнале будет появляться запись:

[Information] New message in chat 123456789: Hello

(сюда можно добавить скриншот лога)

Практические рекомендации

  • Middleware должен быть максимально лёгким.

  • Не следует помещать в него бизнес-логику.

  • Не рекомендуется выполнять долгие блокирующие операции.

  • Следует учитывать порядок выполнения при регистрации нескольких middleware.