♻️🚑️🤖 RabbitMQ: bound the logs queue to prevent unbounded broker memory growth - #9606
♻️🚑️🤖 RabbitMQ: bound the logs queue to prevent unbounded broker memory growth#9606sanderegg wants to merge 5 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #9606 +/- ##
==========================================
- Coverage 88.15% 86.11% -2.05%
==========================================
Files 1559 1112 -447
Lines 60601 46362 -14239
Branches 1583 796 -787
==========================================
- Hits 53421 39923 -13498
+ Misses 6759 6182 -577
+ Partials 421 257 -164
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR enhances the shared RabbitMQClient.subscribe() API (in packages/service-library) with opt-in controls to prevent runaway queue growth and improve high-volume consumer throughput, and then applies those controls specifically to the webserver live-log streaming consumer to protect the RabbitMQ broker from unbounded memory growth.
Changes:
- Added optional
max_length,prefetch_count, andenable_dead_letter_requeueparameters toRabbitMQClient.subscribe(), plus a periodic backlog monitor for bounded queues. - Updated the webserver logs subscription to cap queue depth, increase QoS prefetch, and disable dead-letter-based retries for best-effort log streaming.
- Added service-library tests covering queue max-length behavior, QoS prefetch limiting, retry disabling, and backlog-monitor warning behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| services/web/server/src/simcore_service_webserver/notifications/_rabbitmq_exclusive_queue_consumers.py | Applies bounded-queue + higher prefetch + no-retry semantics to the live log streaming subscription to protect the broker. |
| packages/service-library/src/servicelib/rabbitmq/_client.py | Extends RabbitMQClient.subscribe() with queue bounding, configurable QoS prefetch, optional retry-via-DLX, and a periodic backlog monitor. |
| packages/service-library/tests/rabbitmq/test_rabbitmq.py | Adds tests validating the new subscription options and backlog monitor logging. |
Suppressed comments (1)
packages/service-library/src/servicelib/rabbitmq/_client.py:333
- Even though
enable_dead_letter_requeueis documented correctly here, the earliermessage_handlerparameter docs still state that failures are always "redelivered". With this flag set to False, failures/expirations are dropped, so themessage_handlerdocs should be updated to avoid misleading API consumers.
"When True (default), messages that are nacked or that expire after sitting "
"`message_ttl` in the queue are bounced through a delay queue and re-published into "
"THIS SAME exchange for a retry, up to `unexpected_error_max_attempts` times. Set False "
"for best-effort/fire-and-forget exchanges (e.g. live UI notifications) where a stale "
"message has no value: expired/nacked messages are then simply dropped instead of "
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
a5ab55b to
2f7d094
Compare
| else 0 | ||
| ) | ||
| if consecutive_growth >= _BACKLOG_MONITOR_CONSECUTIVE_GROWTH_TO_WARN: | ||
| _logger.warning( |
There was a problem hiding this comment.
would be nice to expose it as metrics and introduce alert based on it
YuryHrytsuk
left a comment
There was a problem hiding this comment.
Brief and to the point.
Very nice!
b84d4c9 to
934948c
Compare
|



What do these changes do?
This PR adds three new opt-in parameters to
RabbitMQClient.subscribe()(packages/service-library) — none change behavior for any existing exchange/service, since they all default toNone/current behavior:max_length— caps queue depth viax-max-length+x-overflow: drop-head, so a runaway queue drops its oldest messages instead of growing unbounded. Acts as a last-resort circuit breaker, not a routine control.prefetch_count— lets a subscriber override the hardcoded default QoS (1 for shared queues / 10 for exclusive queues), which is otherwise a hard throughput ceiling regardless of how fast the handler runs.enable_dead_letter_requeue— lets a subscriber disable the nack/TTL-expiry retry-via-requeue machinery, for best-effort/fire-and-forget exchanges where redelivering a stale message is actively harmful rather than useful.WARNINGwhen a bounded queue's depth grows for 3 consecutive checks — an early-warning signal that a consumer can't keep up, using its own dedicated channel to avoid interfering with active consumer traffic. This might need further tuning later on.These are applied to the webserver's
LoggerRabbitMessage(live log streaming) subscription specifically:max_length=1_500_000(headroom above the largest healthy historical burst observed, ~920K messages)prefetch_count=100(within RabbitMQ's own documented optimal range of 100–300)enable_dead_letter_requeue=FalseNo other exchange or service is affected.
Related issue/s
How to test
Dev-ops