Symfony Messenger: Отложенные сообщения не работают как ожидалось

Вопрос или проблема

У меня проблемы с задержкой сообщений в Symfony Messenger. Несмотря на настройку задержек, сообщения обрабатываются немедленно. Вот что я попробовал и наблюдал:

Моя конфигурация messenger.yaml:

framework:
    messenger:
        transports:
            async: 'doctrine://npfactory'
        routing:
            'App\Message\ScheduledTaskMessage': async

Я реализовал сервис TaskDispatcher:

public function dispatchTask(string $serviceClass, string $method, array $parameters = [], int $delay = 0): void
{
    $now = new \DateTimeImmutable();
    $scheduledAt = $now->modify("+{$delay} seconds");

    $message = new TaskMessage($serviceClass, $method, $parameters);
    
    $envelope = new Envelope($message, [
        new DelayStamp($delay * 1000) // DelayStamp ожидает миллисекунды
    ]);
    
    $this->messageBus->dispatch($envelope);
    
    $this->logger->info("Dispatching task", [
        'service' => $serviceClass,
        'method' => $method,
        'delay' => $delay,
        'stamps' => array_map(function($stamp) { return get_class($stamp); }, $envelope->all())
    ]);
}

Я вызываю диспетчер так:

$this->taskDispatcher->dispatchTask('App\Service\EbookCreation\FileMovementService', 'move', $parameters, 10);

Логи показывают, что DelayStamp добавляется корректно:

[2024-10-22T18:32:35.470165+02:00] app.INFO: Envelope created
{“hasDelayStamp”:true,”delayValue”:10000} []
[2024-10-22T18:32:35.471168+02:00] app.INFO: Dispatching task
{“service”:”App\Service\EbookCreation\FileMovementService”,”method”:”move”,”delay”:10,”scheduledAt”:”2024-10-22
18:32:45″,”stamps”:[“Symfony\Component\Messenger\Stamp\DelayStamp”]}
[]

Однако, когда я проверяю таблицу messenger_messages в базе данных, столбцы created_at и available_at имеют идентичные временные метки, что указывает на то, что задержка не применяется.

Я пробовал различные подходы, включая:

  • Настройку конфигурации Messenger
  • Реализацию пользовательских штампов и промежуточного ПО
  • Проверку реализации транспорта Doctrine

Несмотря на эти усилия, сообщения с задержкой по-прежнему обрабатываются немедленно. Я ищу решение, которое не усложняло бы систему, так как она должна работать сразу же с Symfony Messenger. Что я упустил? Как мне заставить сообщения с задержкой корректно работать с Symfony Messenger и транспортом Doctrine?

Среда:

ОС: Debian Linux 12

Версия Symfony: 7.1.3

Версия PHP: 8.3.12 (CLI), 8.2 (Apache2)

База данных: версия MariaDB 10.11.6

Ответ или решение

Проблема с отложенными сообщениями в Symfony Messenger

Введение

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

Анализ ситуации

Ваше текущее пространство конфигурации включает следующее:

framework:
    messenger:
        transports:
            async: 'doctrine://npfactory'
        routing:
            'App\Message\ScheduledTaskMessage': async

Вы используете DelayStamp для добавления задержки к сообщениям, что по идее должно обеспечивать их отложенное выполнение. Однако, как вы заметили, метки created_at и available_at в таблице messenger_messages имеют одинаковые временные отметки, что говорит о том, что задержка не применяется.

Возможные причины проблемы

  1. Конфигурация Doctrine Transport:
    Transport на основе Doctrine не поддерживает задержку сообщений. Это связано с тем, что хранилище сообщений (в данном случае база данных) не реализует логику обработки отложенных сообщений. При использовании Doctrine все сообщения становятся доступны для обработки сразу после их отправки в очередь. Для использования отложенной обработки вам необходимо рассмотреть возможность перехода на другой тип транспорта, такой как Redis или RabbitMQ, которые поддерживают эту функциональность.

  2. Обработка DelayStamp:
    Убедитесь, что у вас есть middleware, который правильно обрабатывает DelayStamp. Если это не так, то это может также привести к тому, что отложенные сообщения будут обрабатываться мгновенно.

  3. Альтернативные решения:
    Если вы хотите продолжать использовать Doctrine, и вам не подходит другой транспорт, можно рассмотреть реализацию собственной логики для задержки обработки сообщений. Это может включать хранение сообщения с задержкой и осуществление проверки в какой-то момент времени для его дальнейшей обработки.

Решение проблемы

Для решения проблемы с отложенными сообщениями в Symfony Messenger, рекомендую следующие шаги:

  1. Измените транспорт:
    Рассмотрите возможность переключения на более подходящий транспорт, который поддерживает задержку. Например, Redis transport может быть идеальным выбором, если вы хотите продолжать работать с отложенными сообщениями.

  2. Проверка Middleware:
    Убедитесь, что вы находитесь на правильной версии Symfony Messenger, которая поддерживает обработку DelayStamp, и что у вас нет middleware, которое перезаписывает логику обработки.

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

Заключение

Отложенные сообщения в Symfony Messenger — это мощный инструмент, требующий правильной настройки транспорта и обработки. Понимание того, как работает ваш текущий транспорт и как без проблем реализовать задержки, поможет оптимизировать ваш процесс. Рассмотрите все предложенные шаги, и, надеюсь, это приведет к правильному решению вашей проблемы с задержанными сообщениями.

Оцените материал
Добавить комментарий

Капча загружается...