Make retry/delay queue durable for RabbitMQ 4.3 compatibility#115
Conversation
RabbitMQ 4.3 flips the `transient_nonexcl_queues` deprecated feature flag
from `permitted_by_default` to `denied_by_default`. The combo means
declaring a queue with `durable=false` AND `exclusive=false`.
Connection::setupDelayQueue() previously called `queue_declare()` with
only `queue`, `nowait`, and `arguments`, so the boolean flags fell back
to php-amqplib's defaults — `durable=false`, `exclusive=false`,
`auto_delete=true` — which is exactly the deprecated combination.
RabbitMQ 4.3 then rejects the declaration with:
INTERNAL_ERROR - Feature `transient_nonexcl_queues` is deprecated.
Declaring the queue as durable resolves it. The queue still auto-cleans
via the existing `x-expires` argument, and durability is the more
correct behavior anyway: it preserves in-flight retry messages across
broker restarts mid-delay (with the previous transient declaration the
queue and its messages were lost).
Adds a unit test asserting the delay queue is declared with durable=true.
|
Is this backwards compatible? Were queues durable before or does this need to be a setting that defaults to false so it is backwards compatible with existing setups using this library? |
|
Fair point, you're right, it's not fully backwards-compatible, and I should've called that out in the PR description. The issue: if an existing setup already has a transient delay/retry queue declared, AMQP will reject the new durable declaration with PRECONDITION_FAILED and close the channel. So users with in-flight retry messages at upgrade time will hit errors until the old queues clear. I didn't add a durable: false opt-in because RabbitMQ 4.3+ refuses the old declaration outright, so defaulting to the previous behavior would ship the lib broken on current Rabbit. Happy to add an upgrade note in the README/CHANGELOG to make this explicit. I could also expose delay.queue.durable as a config option if you'd prefer an escape hatch WDYT? |
RabbitMQ 4.3 changes the default of the
transient_nonexcl_queuesdeprecated feature flag frompermitted_by_defaulttodenied_by_default. This flag covers queues declared with bothdurable=falseandexclusive=false.Connection::setupDelayQueue()callsqueue_declare()passing onlyqueue,nowaitandarguments. The boolean flags therefore use php-amqplib's defaults (durable=false,exclusive=false,auto_delete=true), which matches the deprecated case. On RabbitMQ 4.3, the declaration fails with:Setting
durable=truefixes it. The queue is still auto-cleaned via the existingx-expiresargument, and making it durable is arguably better anyway: retry messages currently in flight survive a broker restart during the delay, whereas before the queue and its messages would be lost.Also adds a unit test that the delay queue is declared with
durable=true.