diff --git a/src/Symfony/Bridge/Monolog/CHANGELOG.md b/src/Symfony/Bridge/Monolog/CHANGELOG.md index 1a7e11615e7d0..0784df83597ab 100644 --- a/src/Symfony/Bridge/Monolog/CHANGELOG.md +++ b/src/Symfony/Bridge/Monolog/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +5.3 +--- + +* Add `ResetLoggersWorkerSubscriber` to reset buffered logs in messenger workers + 5.2.0 ----- diff --git a/src/Symfony/Bridge/Monolog/Messenger/ResetLoggersWorkerSubscriber.php b/src/Symfony/Bridge/Monolog/Messenger/ResetLoggersWorkerSubscriber.php new file mode 100644 index 0000000000000..ad38c8d67e4ff --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Messenger/ResetLoggersWorkerSubscriber.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Messenger; + +use Monolog\ResettableInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent; +use Symfony\Component\Messenger\Event\WorkerMessageHandledEvent; + +/** + * Reset loggers between messages being handled to release buffered handler logs. + * + * @author Laurent VOULLEMIER + */ +class ResetLoggersWorkerSubscriber implements EventSubscriberInterface +{ + private $loggers; + + public function __construct(iterable $loggers) + { + $this->loggers = $loggers; + } + + public static function getSubscribedEvents(): array + { + return [ + WorkerMessageHandledEvent::class => 'resetLoggers', + WorkerMessageFailedEvent::class => 'resetLoggers', + ]; + } + + public function resetLoggers(): void + { + foreach ($this->loggers as $logger) { + if ($logger instanceof ResettableInterface) { + $logger->reset(); + } + } + } +} diff --git a/src/Symfony/Bridge/Monolog/Tests/Messenger/ResetLoggersWorkerSubscriberTest.php b/src/Symfony/Bridge/Monolog/Tests/Messenger/ResetLoggersWorkerSubscriberTest.php new file mode 100644 index 0000000000000..23e2f829e1baa --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Tests/Messenger/ResetLoggersWorkerSubscriberTest.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Tests\Messenger; + +use Monolog\Handler\BufferHandler; +use Monolog\Handler\TestHandler; +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Logger; +use Symfony\Bridge\Monolog\Messenger\ResetLoggersWorkerSubscriber; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Messenger\Envelope; +use Symfony\Component\Messenger\Event\WorkerRunningEvent; +use Symfony\Component\Messenger\Handler\HandlersLocator; +use Symfony\Component\Messenger\MessageBus; +use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware; +use Symfony\Component\Messenger\Transport\Receiver\ReceiverInterface; +use Symfony\Component\Messenger\Worker; + +class ResetLoggersWorkerSubscriberTest extends TestCase +{ + public function testLogsAreFlushed() + { + $loggerTestHandler = new TestHandler(); + $loggerTestHandler->setSkipReset(true); + + $logger = new Logger('', [new BufferHandler($loggerTestHandler)]); + + $message = new class() { + }; + + $handler = static function (object $message) use ($logger): void { + $logger->info('Message of class {class} is being handled', ['class' => \get_class($message)]); + }; + + $handlersMiddleware = new HandleMessageMiddleware(new HandlersLocator([ + \get_class($message) => [$handler], + ])); + + $eventDispatcher = new EventDispatcher(); + $eventDispatcher->addSubscriber(new ResetLoggersWorkerSubscriber([$logger])); + $eventDispatcher->addListener(WorkerRunningEvent::class, static function (WorkerRunningEvent $event): void { + $event->getWorker()->stop(); // Limit the worker to one loop + }); + + $bus = new MessageBus([$handlersMiddleware]); + $worker = new Worker([$this->createReceiver($message)], $bus, $eventDispatcher); + $worker->run(); + + $this->assertCount(1, $loggerTestHandler->getRecords()); + } + + private function createReceiver(object $message): ReceiverInterface + { + return new class($message) implements ReceiverInterface { + private $message; + + public function __construct(object $message) + { + $this->message = $message; + } + + public function get(): iterable + { + return [new Envelope($this->message)]; + } + + public function ack(Envelope $envelope): void + { + } + + public function reject(Envelope $envelope): void + { + } + }; + } +} diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index 1eee4ac2d2596..b7cc4f200af58 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -28,7 +28,8 @@ "symfony/security-core": "^4.4|^5.0", "symfony/var-dumper": "^4.4|^5.0", "symfony/mailer": "^4.4|^5.0", - "symfony/mime": "^4.4|^5.0" + "symfony/mime": "^4.4|^5.0", + "symfony/messenger": "^4.4|^5.0" }, "conflict": { "symfony/console": "<4.4", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy