From 2aef839f41da8cc270a34b17018ad0a747030244 Mon Sep 17 00:00:00 2001 From: Warxcell Date: Tue, 15 Mar 2022 09:39:33 +0200 Subject: [PATCH] Fixes #43866 configurable stop signals for messenger --- .../DependencyInjection/Configuration.php | 14 +++ .../FrameworkExtension.php | 8 +- .../Resources/config/messenger.php | 4 +- .../DependencyInjection/ConfigurationTest.php | 100 ++++++++++++++++++ .../Fixtures/php/messenger.php | 1 + .../Fixtures/yml/messenger.yml | 1 + .../StopWorkerOnSigtermSignalListener.php | 29 +---- 7 files changed, 127 insertions(+), 30 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 95380248a3ed8..b078b8e77a5ff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -1308,6 +1308,20 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode, callable $en ->then(static function (array $v): void { throw new InvalidConfigurationException(sprintf('The specified default bus "%s" is not configured. Available buses are "%s".', $v['default_bus'], implode('", "', array_keys($v['buses'])))); }) ->end() ->children() + ->arrayNode('stop_signals') + ->fixXmlConfig('stop_signal') + ->beforeNormalization() + ->ifString() + ->then(static fn (string $value): int => constant($value)) + ->castToArray() + ->end() + ->validate() + ->ifTrue(static fn ($v): bool => !function_exists('pcntl_signal')) + ->then(static function (): void { throw new InvalidConfigurationException('You must install pcntl extension in order to use stop_signals.'); }) + ->ifNull() + ->then(static function (): void { throw new InvalidConfigurationException('Invalid signal passed to stop_signals'); }) + ->end() + ->end() ->arrayNode('routing') ->normalizeKeys(false) ->useAttributeAsKey('message_class') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 733341eeb2c7b..706acd6e1c60e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -706,9 +706,9 @@ private function registerHttpCacheConfiguration(array $config, ContainerBuilder if ($httpMethodOverride) { $container->getDefinition('http_cache') - ->addArgument((new Definition('void')) - ->setFactory([Request::class, 'enableHttpMethodParameterOverride']) - ); + ->addArgument((new Definition('void')) + ->setFactory([Request::class, 'enableHttpMethodParameterOverride']) + ); } } @@ -1914,6 +1914,8 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder $config['default_bus'] = key($config['buses']); } + $container->getDefinition('stop_worker_on_sigterm_signal_listener')->setArgument('$signals', $config['stop_signals']); + $defaultMiddleware = [ 'before' => [ ['id' => 'add_bus_name_stamp_middleware'], diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php index 813d503000de4..87574cd614c16 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php @@ -23,6 +23,7 @@ use Symfony\Component\Messenger\EventListener\SendFailedMessageToFailureTransportListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnCustomStopExceptionListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnRestartSignalListener; +use Symfony\Component\Messenger\EventListener\StopWorkerOnSignalListener; use Symfony\Component\Messenger\EventListener\StopWorkerOnSigtermSignalListener; use Symfony\Component\Messenger\Middleware\AddBusNameStampMiddleware; use Symfony\Component\Messenger\Middleware\DispatchAfterCurrentBusMiddleware; @@ -192,8 +193,9 @@ ->tag('kernel.event_subscriber') ->tag('monolog.logger', ['channel' => 'messenger']) - ->set('messenger.listener.stop_worker_on_sigterm_signal_listener', StopWorkerOnSigtermSignalListener::class) + ->set('messenger.listener.stop_worker_on_signal_listener', StopWorkerOnSignalListener::class) ->args([ + abstract_arg('signals'), service('logger')->ignoreOnInvalid(), ]) ->tag('kernel.event_subscriber') diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 1b154cb76f2a9..1c67ae85bf92b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -265,6 +265,106 @@ public function testLockMergeConfigs() ); } + public function testMessengerWithoutPcntl() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $config = $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + ], + ], + ]); + + self::assertEquals([\SIGTERM], $config['framework']['messenger']['stop_signals']); + } + + public function testMessengerWithPcntlWithoutExplicitlyConfigured() + { + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('You must install pcntl extension in order to use stop_signals.'); + $processor = new Processor(); + $configuration = new Configuration(true); + + $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + 'stop_signals' => \SIGTERM + ], + ], + ]); + } + + public function testMessengerWithoutPcntlWithoutStopSignals() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + ], + ], + ]); + + $this->expectNotToPerformAssertions(); + } + + public function testMessengerWithInvalidSignal() + { + $this->expectException(InvalidConfigurationException::class); + $this->expectExceptionMessage('Invalid signal passed to stop_signals'); + $processor = new Processor(); + $configuration = new Configuration(true); + + $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + 'stop_signals' => \SIG_IGN + ], + ], + ]); + } + + public function testMessengerWithMultipleStopSignals() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $config = $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + 'stop_signals' => [\SIGTERM, \SIGQUIT] + ], + ], + ]); + + static::assertEquals( + [\SIGTERM, \SIGQUIT], + $config['messenger']['stop_signals'] + ); + } + + public function testMessengerWithStringStopSignal() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $config = $processor->processConfiguration($configuration, [ + 'framework' => [ + 'messenger' => [ + 'stop_signals' => ['SIGTERM', 'SIGQUIT'] + ], + ], + ]); + + static::assertEquals( + [\SIGTERM, \SIGQUIT], + $config['messenger']['stop_signals'] + ); + } + public function testItShowANiceMessageIfTwoMessengerBusesAreConfiguredButNoDefaultBus() { $expectedMessage = 'You must specify the "default_bus" if you define more than one bus.'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php index adb8239d04737..9b0c185293ca4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/messenger.php @@ -4,6 +4,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; $container->loadFromExtension('framework', [ + 'stop_signals'=> \SIGTERM, 'messenger' => [ 'routing' => [ FooMessage::class => ['sender.bar', 'sender.biz'], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml index 82fea3b27af23..81650eac2c513 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/messenger.yml @@ -1,5 +1,6 @@ framework: messenger: + stop_signals: SIGTERM routing: 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage': ['sender.bar', 'sender.biz'] 'Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\BarMessage': 'sender.foo' diff --git a/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php b/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php index 7991c6cfd25ee..17bedc39e3985 100644 --- a/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php +++ b/src/Symfony/Component/Messenger/EventListener/StopWorkerOnSigtermSignalListener.php @@ -12,38 +12,15 @@ namespace Symfony\Component\Messenger\EventListener; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Messenger\Event\WorkerStartedEvent; /** * @author Tobias Schultze + * @deprecated Use StopWorkerOnSignalListener instead. */ -class StopWorkerOnSigtermSignalListener implements EventSubscriberInterface +class StopWorkerOnSigtermSignalListener extends StopWorkerOnSignalListener { - private ?LoggerInterface $logger; - public function __construct(LoggerInterface $logger = null) { - $this->logger = $logger; - } - - public function onWorkerStarted(WorkerStartedEvent $event): void - { - pcntl_signal(\SIGTERM, function () use ($event) { - $this->logger?->info('Received SIGTERM signal.', ['transport_names' => $event->getWorker()->getMetadata()->getTransportNames()]); - - $event->getWorker()->stop(); - }); - } - - public static function getSubscribedEvents(): array - { - if (!\function_exists('pcntl_signal')) { - return []; - } - - return [ - WorkerStartedEvent::class => ['onWorkerStarted', 100], - ]; + parent::__construct(\SIGTERM, $logger); } }