Вопрос или проблема
У меня проблемы с задержкой сообщений в 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
имеют одинаковые временные отметки, что говорит о том, что задержка не применяется.
Возможные причины проблемы
-
Конфигурация Doctrine Transport:
Transport на основе Doctrine не поддерживает задержку сообщений. Это связано с тем, что хранилище сообщений (в данном случае база данных) не реализует логику обработки отложенных сообщений. При использовании Doctrine все сообщения становятся доступны для обработки сразу после их отправки в очередь. Для использования отложенной обработки вам необходимо рассмотреть возможность перехода на другой тип транспорта, такой как Redis или RabbitMQ, которые поддерживают эту функциональность. -
Обработка
DelayStamp
:
Убедитесь, что у вас есть middleware, который правильно обрабатываетDelayStamp
. Если это не так, то это может также привести к тому, что отложенные сообщения будут обрабатываться мгновенно. -
Альтернативные решения:
Если вы хотите продолжать использовать Doctrine, и вам не подходит другой транспорт, можно рассмотреть реализацию собственной логики для задержки обработки сообщений. Это может включать хранение сообщения с задержкой и осуществление проверки в какой-то момент времени для его дальнейшей обработки.
Решение проблемы
Для решения проблемы с отложенными сообщениями в Symfony Messenger, рекомендую следующие шаги:
-
Измените транспорт:
Рассмотрите возможность переключения на более подходящий транспорт, который поддерживает задержку. Например, Redis transport может быть идеальным выбором, если вы хотите продолжать работать с отложенными сообщениями. -
Проверка Middleware:
Убедитесь, что вы находитесь на правильной версии Symfony Messenger, которая поддерживает обработкуDelayStamp
, и что у вас нет middleware, которое перезаписывает логику обработки. -
Настройка логики задержки:
Если переключение транспорта невозможно, создайте собственное решение для имитации задержки сообщений, где вы будете отслеживать время отправки и управлять обработкой сообщений самостоятельно.
Заключение
Отложенные сообщения в Symfony Messenger — это мощный инструмент, требующий правильной настройки транспорта и обработки. Понимание того, как работает ваш текущий транспорт и как без проблем реализовать задержки, поможет оптимизировать ваш процесс. Рассмотрите все предложенные шаги, и, надеюсь, это приведет к правильному решению вашей проблемы с задержанными сообщениями.