From c2e84c610a97ea9a8827717704c9619b7cc458c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 22 Dec 2020 12:19:39 +0100 Subject: [PATCH] Setup queues once in AMQP --- .../Bridge/AmazonSqs/Transport/Connection.php | 2 +- .../Amqp/Tests/Transport/ConnectionTest.php | 18 ++++++++ .../Bridge/Amqp/Transport/Connection.php | 46 +++++++------------ 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php index f2408dc0588c8..7ccd5889e8e12 100644 --- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Transport/Connection.php @@ -118,7 +118,7 @@ public static function fromDsn(string $dsn, array $options = [], HttpClientInter 'wait_time' => (int) $options['wait_time'], 'poll_timeout' => $options['poll_timeout'], 'visibility_timeout' => $options['visibility_timeout'], - 'auto_setup' => (bool) $options['auto_setup'], + 'auto_setup' => filter_var($options['auto_setup'], \FILTER_VALIDATE_BOOLEAN), 'queue_name' => (string) $options['queue_name'], ]; diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php index 36fde1250587c..db8c5e1bb23e9 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/ConnectionTest.php @@ -421,6 +421,24 @@ public function testItCanDisableTheSetup() $connection->publish('body'); } + public function testItSetupQueuesOnce() + { + $factory = new TestAmqpFactory( + $amqpConnection = $this->createMock(\AMQPConnection::class), + $amqpChannel = $this->createMock(\AMQPChannel::class), + $amqpQueue = $this->createMock(\AMQPQueue::class), + $amqpExchange = $this->createMock(\AMQPExchange::class) + ); + + $amqpExchange->expects($this->once())->method('declareExchange'); + $amqpQueue->expects($this->once())->method('declareQueue'); + $amqpQueue->expects($this->once())->method('bind'); + + $connection = Connection::fromDsn('amqp://localhost', ['auto_setup' => true], $factory); + $connection->publish('body'); + $connection->publish('body'); + } + public function testSetChannelPrefetchWhenSetup() { $factory = new TestAmqpFactory( diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php index 5c7e76291060d..d48c5474c2efe 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php @@ -79,6 +79,8 @@ class Connection private $exchangeOptions; private $queuesOptions; private $amqpFactory; + private $autoSetupExchange; + private $autoSetup; /** * @var \AMQPChannel|null @@ -112,6 +114,7 @@ public function __construct(array $connectionOptions, array $exchangeOptions, ar 'queue_name_pattern' => 'delay_%exchange_name%_%routing_key%_%delay%', ], ], $connectionOptions); + $this->autoSetupExchange = $this->autoSetup = $connectionOptions['auto_setup'] ?? true; $this->exchangeOptions = $exchangeOptions; $this->queuesOptions = $queuesOptions; $this->amqpFactory = $amqpFactory ?: new AmqpFactory(); @@ -207,6 +210,9 @@ public static function fromDsn(string $dsn, array $options = [], AmqpFactory $am $exchangeOptions = $amqpOptions['exchange']; $queuesOptions = $amqpOptions['queues']; unset($amqpOptions['queues'], $amqpOptions['exchange']); + if (isset($amqpOptions['auto_setup'])) { + $amqpOptions['auto_setup'] = filter_var($amqpOptions['auto_setup'], \FILTER_VALIDATE_BOOLEAN); + } $queuesOptions = array_map(function ($queueOptions) { if (!\is_array($queueOptions)) { @@ -285,7 +291,7 @@ public function publish(string $body, array $headers = [], int $delayInMs = 0, A return; } - if ($this->shouldSetup()) { + if ($this->autoSetupExchange) { $this->setupExchangeAndQueues(); } @@ -347,7 +353,7 @@ private function publishOnExchange(\AMQPExchange $exchange, string $body, string private function setupDelay(int $delay, ?string $routingKey) { - if ($this->shouldSetup()) { + if ($this->autoSetup) { $this->setup(); // setup delay exchange and normal exchange for delay queue to DLX messages to } @@ -418,23 +424,12 @@ public function get(string $queueName): ?\AMQPEnvelope { $this->clearWhenDisconnected(); - if ($this->shouldSetup()) { + if ($this->autoSetupExchange) { $this->setupExchangeAndQueues(); } - try { - if (false !== $message = $this->queue($queueName)->get()) { - return $message; - } - } catch (\AMQPQueueException $e) { - if (404 === $e->getCode() && $this->shouldSetup()) { - // If we get a 404 for the queue, it means we need to set up the exchange & queue. - $this->setupExchangeAndQueues(); - - return $this->get($queueName); - } - - throw $e; + if (false !== $message = $this->queue($queueName)->get()) { + return $message; } return null; @@ -452,8 +447,11 @@ public function nack(\AMQPEnvelope $message, string $queueName, int $flags = \AM public function setup(): void { - $this->setupExchangeAndQueues(); + if ($this->autoSetupExchange) { + $this->setupExchangeAndQueues(); + } $this->getDelayExchange()->declareExchange(); + $this->autoSetup = false; } private function setupExchangeAndQueues(): void @@ -466,6 +464,7 @@ private function setupExchangeAndQueues(): void $this->queue($queueName)->bind($this->exchangeOptions['name'], $bindingKey, $queueConfig['binding_arguments'] ?? []); } } + $this->autoSetupExchange = false; } /** @@ -558,19 +557,6 @@ private function clearWhenDisconnected(): void } } - private function shouldSetup(): bool - { - if (!\array_key_exists('auto_setup', $this->connectionOptions)) { - return true; - } - - if (\in_array($this->connectionOptions['auto_setup'], [false, 'false'], true)) { - return false; - } - - return true; - } - private function getDefaultPublishRoutingKey(): ?string { return $this->exchangeOptions['default_publish_routing_key'] ?? null;