Fix RabbitMQ 4.x crash: global QoS not supported on classic queues#2481
Fix RabbitMQ 4.x crash: global QoS not supported on classic queues#2481Azd325 wants to merge 3 commits intocelery:mainfrom
Conversation
RabbitMQ 4.0 removed support for global QoS prefetch (`basic.qos` with `global=true`) on classic queues. When Kombu connected to a RabbitMQ 4.x broker, `qos_semantics_matches_spec` returned `False` (because the version was not < 3.3), causing Celery to set `global=True` in its QoS call, which RabbitMQ 4.x immediately rejected with: 540 NOT_IMPLEMENTED - queue does not support global qos This crashed workers on startup before they could consume any tasks. Fix the version boundary check in both `pyamqp` and `librabbitmq` transports to return `True` (per-channel QoS) for RabbitMQ >= 4.0: Before: version < (3, 3) After: version < (3, 3) or version >= (4, 0) This restores the correct behavior: - RabbitMQ < 3.3: True (spec-compliant per-channel QoS) - RabbitMQ 3.3–3.x: False (global QoS semantics) - RabbitMQ 4.0+: True (global QoS removed, per-channel only) RabbitMQ deprecation announcement (2021): https://www.rabbitmq.com/blog/2021/08/21/4.0-deprecation-announcements RabbitMQ 4.x classic queues docs (global QoS removal): https://www.rabbitmq.com/docs/classic-queues Closes: celery#2469
There was a problem hiding this comment.
Pull request overview
This PR fixes a startup crash when Kombu connects to a RabbitMQ 4.x broker using the pyamqp or librabbitmq transports. RabbitMQ 4.0 removed support for global QoS prefetch on classic queues, but the old version boundary check (version < (3, 3)) returned False for all RabbitMQ ≥ 3.3, causing Celery to set global=True in its QoS call — which RabbitMQ 4.x rejects with a 540 NOT_IMPLEMENTED error.
Changes:
- Fix the version boundary in
pyamqp.Transport.qos_semantics_matches_specto returnTruefor RabbitMQ ≥ 4.0. - Apply the same fix symmetrically to
librabbitmq.Transport.qos_semantics_matches_spec, and add safe handling for a missingversionkey in both transports. - Add comprehensive unit tests for both transports covering all version boundary cases and the missing-version edge case.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
kombu/transport/pyamqp.py |
Core fix: adds RabbitMQ 4.0+ condition and safe version key handling |
kombu/transport/librabbitmq.py |
Same fix applied symmetrically to the librabbitmq transport |
t/unit/transport/test_pyamqp.py |
New tests for all QoS version boundary cases in pyamqp |
t/unit/transport/test_librabbitmq.py |
New tests for all QoS version boundary cases in librabbitmq, including the AttributeError path |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2481 +/- ##
==========================================
+ Coverage 82.23% 82.24% +0.01%
==========================================
Files 79 79
Lines 10080 10088 +8
Branches 1150 1152 +2
==========================================
+ Hits 8289 8297 +8
Misses 1589 1589
Partials 202 202 ☔ View full report in Codecov by Sentry. |
auvipy
left a comment
There was a problem hiding this comment.
we should keep support for both old and new versions for easier migrations
auvipy
left a comment
There was a problem hiding this comment.
also can you improve test coverage?
|
LGTM! 🚀 |
|
the codecov is showing very low coverage |
RabbitMQ 4.0 removed support for global QoS prefetch (
basic.qoswithglobal=true) on classic queues. When Kombu connected to a RabbitMQ 4.x broker,qos_semantics_matches_specreturnedFalse(because the version was not < 3.3), causing Celery to setglobal=Truein its QoS call, which RabbitMQ 4.x immediately rejected with:540 NOT_IMPLEMENTED - queue does not support global qos
This crashed workers on startup before they could consume any tasks.
Fix the version boundary check in both
pyamqpandlibrabbitmqtransports to returnTrue(per-channel QoS) for RabbitMQ >= 4.0:Before: version < (3, 3)
After: version < (3, 3) or version >= (4, 0)
This restores the correct behavior:
RabbitMQ deprecation announcement (2021):
https://www.rabbitmq.com/blog/2021/08/21/4.0-deprecation-announcements
RabbitMQ 4.x classic queues docs (global QoS removal):
https://www.rabbitmq.com/docs/classic-queues
Closes: #2469