Add the rabbitmq module

This commit is contained in:
2026-08-29 09:58:34 +05:30
parent 3a682e496e
commit de9fc5ce4c
27 changed files with 1523 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
[← Acknowledgement](05-acknowledgement.md) · [Module README](../README.md)
# 6. Changing your mind about a queue
Queue arguments are immutable. There is no `ALTER QUEUE`. Redeclaring an existing queue with
different arguments is a channel-level error
([`docs/output/precondition-failed.txt`](output/precondition-failed.txt)):
```
PRECONDITION_FAILED - inequivalent arg 'x-message-ttl' for queue 'orders.ttl' in vhost '/':
received '9999' but current is '1500', class-id=50, method-id=10
```
Reply code **406**. The message is precise and helpful, and you will probably never see it,
because of what Spring wraps it in:
```
AmqpIOException: java.io.IOException
caused by: null
caused by: channel error; protocol method: #method<channel.close>(reply-code=406, ...)
```
`AmqpIOException`'s own message is the string `java.io.IOException`. The next cause's message is
`null`. The useful text is two levels down. This is why the failure gets reported as "some
IOException from RabbitMQ" and why it is worth writing a log statement that walks the cause
chain.
## What this means operationally
Changing a TTL, a max-length, a dead-letter exchange or a queue type on a live queue is not a
config edit. It is a migration:
1. declare the new queue under a new name
2. bind it alongside the old one
3. move consumers over
4. drain the old queue
5. delete it
Plan the rename into the change from the start — `orders.work.v2` is not ugly, it is honest.
## Related failure modes
**A failed declaration stops the ones after it.** `RabbitAdmin` declares beans on connection, and
a `PRECONDITION_FAILED` closes the channel. Declarations queued behind it on that channel do not
happen. So one stale queue argument can leave half your topology undeclared, and the symptom is a
*different* queue being missing.
**Declarations happen on connection, not on context refresh.** A broken topology does not fail
startup; it fails the first publish. If you want it to fail at boot, force a connection early —
`connectionFactory.createConnection()` in an `ApplicationRunner` is enough.
**`missing-queues-fatal` defaults differently for the two container types.** It is `true` for
`spring.rabbitmq.listener.simple` and `false` for `spring.rabbitmq.listener.direct`. So the same
missing queue kills a simple container and is quietly tolerated by a direct one, which makes
"it works in that service" an unhelpful data point. Combined with the point above, a topology
error can present as a listener startup problem in one service and as silence in another.
[Module README](../README.md)