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#2481auvipy merged 4 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 10081 10089 +8
Branches 1150 1152 +2
==========================================
+ Hits 8290 8298 +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 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
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