Новое в Symfony 7.2: Keepalive сообщения транспорта
keepalive
для транспортов Messenger, предотвращающая таймауты при обработке сообщений.- Pull Request: [Console][Messenger] Asynchronously notify transports which messages are still being processed #53508 HypeMC
- Pull Request: [Console] Add ability to schedule alarm signals and a
ConsoleAlarmEvent
#53533 HypeMC
Некоторые транспорты, используемые в компоненте Messenger, имеют таймаут, определяющий, как долго сообщение считается в обработке
. Если сообщение не обрабатывается в течение этого времени, оно возвращается в очередь ожидающих сообщений, что может привести к его многократной обработке. В Symfony 7.2 мы решаем эту проблему двумя способами.
Во-первых, мы ввели функцию keepalive для Messenger. Новый интерфейс KeepaliveReceiverInterface
, который может опционально реализовываться транспортами, определяет следующий метод:
/**
* Информирует транспорт, что сообщение всё ещё обрабатывается, что позволяет избежать таймаута на стороне транспорта.
*
* @throws TransportException Если возникли проблемы со связью с транспортом
*/
public function keepalive(Envelope $envelope): void;
Некоторые из встроенных транспортов уже обновлены для реализации этого интерфейса, и мы продолжим обновлять остальные в будущих версиях Symfony.
Во-вторых, мы добавили ConsoleAlarmEvent
для оповещения о сигнале \SIGALRM
и включили консольные команды для планирования аварийных сигналов. Главный класс Application
, расширяемый всеми консольными приложениями Symfony, теперь включает следующий метод:
// Устанавливает интервал для планирования сигнала SIGALRM в секундах.
public function setAlarmInterval(?int $seconds): void
Благодаря этой новой функции мы обновили команды messenger:consume
и messenger:failed:retry
, добавив новую опцию --keepalive
. Это усовершенствование позволяет командам Messenger выполнять следующую логику:
private const DEFAULT_KEEPALIVE_INTERVAL = 5;
// ...
// планирование отправки SIGALRM каждые N секунд
if ($input->hasParameterOption('--keepalive')) {
$this->getApplication()->setAlarmInterval(
(int) ($input->getOption('keepalive') ?? self::DEFAULT_KEEPALIVE_INTERVAL)
);
}
// ...
// обработка события SIGALARM путём вызова функции транспорта keepalive
public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
{
// ...
if (\SIGALRM === $signal) {
$this->worker->keepalive();
// ...
}
}