Add the rabbitmq module
This commit is contained in:
58
rabbitmq/docs/06-changing-your-mind.md
Normal file
58
rabbitmq/docs/06-changing-your-mind.md
Normal 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)
|
||||
Reference in New Issue
Block a user