From 583f85b7deffddeaf5a4e3219f7455716b6704c1 Mon Sep 17 00:00:00 2001 From: Oleg Krasavin Date: Wed, 22 Sep 2021 14:37:19 +0300 Subject: [PATCH] [Messenger] Add WorkerMetadata to Worker class Add tests for WorkerMetadata class Fix WorkerMetadataTest header Access WorkerMetadata directly via getter and make it mutable. Fix CS Refactor WorkerMetadata::set() method to accept array Use null as default value for queueNames instead of false Add missing return type Make fabbot happy --- src/Symfony/Component/Messenger/CHANGELOG.md | 2 + .../Messenger/Tests/WorkerMetadataTest.php | 57 +++++++++++++++++++ .../Component/Messenger/Tests/WorkerTest.php | 30 ++++++++++ src/Symfony/Component/Messenger/Worker.php | 17 +++++- .../Component/Messenger/WorkerMetadata.php | 47 +++++++++++++++ 5 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Tests/WorkerMetadataTest.php create mode 100644 src/Symfony/Component/Messenger/WorkerMetadata.php diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 889207a17400d..529ba46305d5d 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * Add `StopWorkerExceptionInterface` and its implementation `StopWorkerException` to stop the worker. * Add support for resetting container services after each messenger message. + * Added `WorkerMetadata` class which allows you to access the configuration details of a worker, like `queueNames` and `transportNames` it consumes from. + * New method `getMetadata()` was added to `Worker` class which returns the `WorkerMetadata` object. 5.3 --- diff --git a/src/Symfony/Component/Messenger/Tests/WorkerMetadataTest.php b/src/Symfony/Component/Messenger/Tests/WorkerMetadataTest.php new file mode 100644 index 0000000000000..704ed773ae1a0 --- /dev/null +++ b/src/Symfony/Component/Messenger/Tests/WorkerMetadataTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Messenger\WorkerMetadata; + +/** + * @author Oleg Krasavin + */ +class WorkerMetadataTest extends TestCase +{ + public function testItReturnsDefaultValuesIfNoneProvided() + { + $metadata = new WorkerMetadata([]); + + $this->assertNull($metadata->getQueueNames()); + $this->assertSame([], $metadata->getTransportNames()); + } + + public function testItReturnsProvidedMetadata() + { + $data = [ + 'queueNames' => ['c', 'b', 'a'], + 'transportNames' => ['a', 'b', 'c'], + ]; + + $metadata = new WorkerMetadata($data); + + $this->assertSame($data['queueNames'], $metadata->getQueueNames()); + $this->assertSame($data['transportNames'], $metadata->getTransportNames()); + } + + public function testItSetsMetadataViaSetter() + { + $data = [ + 'queueNames' => ['c', 'b', 'a'], + 'transportNames' => ['a', 'b', 'c'], + ]; + + $metadata = new WorkerMetadata([]); + + $metadata->set($data); + + $this->assertSame($data['queueNames'], $metadata->getQueueNames()); + $this->assertSame($data['transportNames'], $metadata->getTransportNames()); + } +} diff --git a/src/Symfony/Component/Messenger/Tests/WorkerTest.php b/src/Symfony/Component/Messenger/Tests/WorkerTest.php index 48a3014b1176e..6711a0febfea0 100644 --- a/src/Symfony/Component/Messenger/Tests/WorkerTest.php +++ b/src/Symfony/Component/Messenger/Tests/WorkerTest.php @@ -167,6 +167,28 @@ public function testWorkerDispatchesEventsOnError() $worker->run(); } + public function testWorkerContainsMetadata() + { + $envelope = new Envelope(new DummyMessage('Hello')); + $receiver = new DummyQueueReceiver([[$envelope]]); + + $bus = $this->createMock(MessageBusInterface::class); + $bus->method('dispatch')->willReturn($envelope); + + $dispatcher = new EventDispatcher(); + $dispatcher->addListener(WorkerRunningEvent::class, function (WorkerRunningEvent $event) { + $event->getWorker()->stop(); + }); + + $worker = new Worker(['dummyReceiver' => $receiver], $bus, $dispatcher); + $worker->run(['queues' => ['queue1', 'queue2']]); + + $workerMetadata = $worker->getMetadata(); + + $this->assertSame(['queue1', 'queue2'], $workerMetadata->getQueueNames()); + $this->assertSame(['dummyReceiver'], $workerMetadata->getTransportNames()); + } + public function testTimeoutIsConfigurable() { $apiMessage = new DummyMessage('API'); @@ -359,3 +381,11 @@ public function getAcknowledgedEnvelopes(): array return $this->acknowledgedEnvelopes; } } + +class DummyQueueReceiver extends DummyReceiver implements QueueReceiverInterface +{ + public function getFromQueues(array $queueNames): iterable + { + return $this->get(); + } +} diff --git a/src/Symfony/Component/Messenger/Worker.php b/src/Symfony/Component/Messenger/Worker.php index f13edcc2f5a05..f32117529dbbe 100644 --- a/src/Symfony/Component/Messenger/Worker.php +++ b/src/Symfony/Component/Messenger/Worker.php @@ -42,6 +42,7 @@ class Worker private $eventDispatcher; private $logger; private $shouldStop = false; + private $metadata; /** * @param ReceiverInterface[] $receivers Where the key is the transport name @@ -52,6 +53,9 @@ public function __construct(array $receivers, MessageBusInterface $bus, EventDis $this->bus = $bus; $this->logger = $logger; $this->eventDispatcher = class_exists(Event::class) ? LegacyEventDispatcherProxy::decorate($eventDispatcher) : $eventDispatcher; + $this->metadata = new WorkerMetadata([ + 'transportNames' => array_keys($receivers), + ]); } /** @@ -63,12 +67,14 @@ public function __construct(array $receivers, MessageBusInterface $bus, EventDis */ public function run(array $options = []): void { - $this->dispatchEvent(new WorkerStartedEvent($this)); - $options = array_merge([ 'sleep' => 1000000, ], $options); - $queueNames = $options['queues'] ?? false; + $queueNames = $options['queues'] ?? null; + + $this->metadata->set(['queueNames' => $queueNames]); + + $this->dispatchEvent(new WorkerStartedEvent($this)); if ($queueNames) { // if queue names are specified, all receivers must implement the QueueReceiverInterface @@ -173,6 +179,11 @@ public function stop(): void $this->shouldStop = true; } + public function getMetadata(): WorkerMetadata + { + return $this->metadata; + } + private function dispatchEvent(object $event): void { if (null === $this->eventDispatcher) { diff --git a/src/Symfony/Component/Messenger/WorkerMetadata.php b/src/Symfony/Component/Messenger/WorkerMetadata.php new file mode 100644 index 0000000000000..0eaab06b712d6 --- /dev/null +++ b/src/Symfony/Component/Messenger/WorkerMetadata.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger; + +/** + * @author Oleg Krasavin + */ +final class WorkerMetadata +{ + private $metadata; + + public function __construct(array $metadata) + { + $this->metadata = $metadata; + } + + public function set(array $newMetadata): void + { + $this->metadata = array_merge($this->metadata, $newMetadata); + } + + /** + * Returns the queue names the worker consumes from, if "--queues" option was used. + * Returns null otherwise. + */ + public function getQueueNames(): ?array + { + return $this->metadata['queueNames'] ?? null; + } + + /** + * Returns an array of unique identifiers for transport receivers the worker consumes from. + */ + public function getTransportNames(): array + { + return $this->metadata['transportNames'] ?? []; + } +}