Skip to content

[AmqpMessenger] Allow using the default amqp exchange #45784

@d-ph

Description

@d-ph

Description

I would like to request that the AmqpMessenger allows using the default AMQP Exchange. I.e. a setup, where there isn't a pair of an Exchange and a Queue for each Messenger's Transport, but rather a single Exchange (the default one) and a separate Queue for each Transport.

This is already supported in AMQP, RabbitMQ and php/ext-amqp -- one just has to use the special, "well-known" Exchange name '' (an empty string) to indicate to the AMQP protocol that the default Exchange is desired to be used.

Adding this feature to AmqpMessenger requires that the AMQP Exchange is not attempted to be declared (or bound to any Queue), if its name is an empty string. In other words, the required change is minimal. Please see the before/after in the examples below.

Apart from the code change, it might be worthwhile to mention this use case in the online documentation, in the "exchange[name]" option description.

Thank you.

Example

The default AMQP Exchange is directing the queue messages to Queues based on the supplied routing key when dispatching a queue message. For this reason, it's best to use the following Messenger configuration at a minimum:

transports:
  my_queue:
    dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
    options:
      exchange:
        # Indicates that the default Exchange is to be used
        name: ''
        # Makes the default Exchange direct the queue messages to the desired Queue
        default_publish_routing_key: my_queue

      queues:
        my_queue: {}

The current code always attempts to declare the Exchange. The following 2 code changes are needed to make it not do that if the exchange name is an empty string:

  1. https://github.com/symfony/amqp-messenger/blob/3c6563c2a6d5c343281fc35922498afb909ea13a/Transport/Connection.php#L522
public function exchange(): \AMQPExchange
{
    if (!isset($this->amqpExchange)) {
        $this->amqpExchange = $this->amqpFactory->createExchange($this->channel());
        $this->amqpExchange->setName($this->exchangeOptions['name']);
-        $this->amqpExchange->setType($this->exchangeOptions['type'] ?? \AMQP_EX_TYPE_FANOUT);
-        $this->amqpExchange->setFlags($this->exchangeOptions['flags'] ?? \AMQP_DURABLE);
-
-        if (isset($this->exchangeOptions['arguments'])) {
-            $this->amqpExchange->setArguments($this->exchangeOptions['arguments']);
-        }
+
+        if ($this->exchangeOptions['name'] !== '') {
+            $this->amqpExchange->setType($this->exchangeOptions['type'] ?? \AMQP_EX_TYPE_FANOUT);
+            $this->amqpExchange->setFlags($this->exchangeOptions['flags'] ?? \AMQP_DURABLE);
+
+            if (isset($this->exchangeOptions['arguments'])) {
+                $this->amqpExchange->setArguments($this->exchangeOptions['arguments']);
+            }
+        }

    }

    return $this->amqpExchange;
}
  1. https://github.com/symfony/amqp-messenger/blob/3c6563c2a6d5c343281fc35922498afb909ea13a/Transport/Connection.php#L447
private function setupExchangeAndQueues(): void
{
-    $this->exchange()->declareExchange();
+    $this->exchange();
+    if ($this->exchangeOptions['name'] !== '') {
+        $this->exchange()->declareExchange();
+    }

    foreach ($this->queuesOptions as $queueName => $queueConfig) {
        $this->queue($queueName)->declareQueue();
-        foreach ($queueConfig['binding_keys'] ?? [null] as $bindingKey) {
-            $this->queue($queueName)->bind($this->exchangeOptions['name'], $bindingKey, $queueConfig['binding_arguments'] ?? []);
-        }
+        if ($this->exchangeOptions['name'] !== '') {
+           foreach ($queueConfig['binding_keys'] ?? [null] as $bindingKey) {
+               $this->queue($queueName)->bind($this->exchangeOptions['name'], $bindingKey, $queueConfig['binding_arguments'] ?? []);
+           }
+        }
    }
    $this->autoSetupExchange = false;
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions