Description
Symfony version(s) affected: 4.3.2
Description
When using the DelayStamp in AMPQ transport the method createDelayQueue
(in AmqpExt/Connection
) creates a temporary queue. The attribute x-message-ttl
is set to some value. After the delay time, the message goes to the target queue (it is transported by some internal mechanism (?), not by a consumer, so there is no consumer attached to that queue). As a result the temporary queue stays empty and it is not going to be removed. According to AMPQ documentation queue is removed by setting attribute auto-delete:true
only if it had at least one consumer:
An auto-delete queue will be deleted when its last consumer is cancelled (e.g. using the basic.cancel in AMQP 0-9-1) or gone (closed channel or connection, or lost TCP connection with the server).
If a queue never had any consumers, for instance, when all consumption happens using the basic.get method (the "pull" API), it wont' be automatically deleted. For such cases, use exclusive queues or queue TTL.
How to reproduce
Dispatch a message using DelayStamp and AMPQ transport, check existing queues i.e in RabbitMQ.
Solution
The solution is to set additionally x-expires
parameter for delay queue in createDelayQueue
method. It ensures that the temporary queue is going to be removed and prevents from creating hundreds of zombie queues.
$queue->setArguments([
'x-message-ttl' => $delay,
'x-expires' => $delay * self::DELAY_MULTIPLIER,
'x-dead-letter-exchange' => $this->exchangeOptions['name'],
// after being released from to DLX, make sure the original routing key will be used
// we must use an empty string instead of null for the argument to be picked up
'x-dead-letter-routing-key' => $routingKey ?? '',
]);
Additional context
n/a