onebeyond / rascal

A config driven wrapper for amqp.node supporting multi-host connections, automatic error recovery, redelivery flood protection, transparent encryption / decryption and channel pooling.
MIT License
451 stars 69 forks source link

Update the queue configuration #204

Closed nico3dfx closed 2 years ago

nico3dfx commented 2 years ago

Hi, I have an environment with N queues inside RabbitMQ. All those queues don't have the "deadLetterRoutingKey" option and now I need it. So with a new rascal configuration I added this option: "assert" is true and "check" is also true but when I start the application I have this message:

Error: Operation failed: QueueDeclare; 406 (PRECONDITION-FAILED) with message "PRECONDITION_FAILED - inequivalent arg 'x-dead-letter-routing-key' for queue 'my_service' in vhost '/': received the value 'service.dlq' of type 'longstr' but current is none"

Is there a way to "update" the queues opitions? Nico.

cressie176 commented 2 years ago

Hi @nico3dfx,

No, unfortunately not. This is a limitation of RabbitMQ. You cannot redefine a queue or exchange. For queues you need to do something like...

Option 1 (keep the existing queue name)

  1. Stop all messages from being published to the queue
  2. Allow the queue to drain
  3. Stop consuming from the queue
  4. Delete the queue
  5. Recreate the queue
  6. Reapply the bindings
  7. Start consuming from the queue again
  8. Allow messages to be published again

Option 2 (use a different queue name)

  1. Create a new queue
  2. Consume from the old and new queue, tolerating duplicates
  3. Start publishing to the new queue
  4. Stop publishing to the old queue
  5. Wait for the old queue to drain
  6. Stop consuming from the old queue
  7. Delete the old queue

There are other options too - for example, you can define a shovel to copy messages from one queue to another, or you could maybe daisy chain queues together where the end queue had the dead letter routing configuration etc, but I'm not aware of any painless options unfortunately.

cressie176 commented 2 years ago

Something else you might consider in too, In RabbitMQ I believe you can define policies based on queue / exchange name. So for example, if you had a standard that said all work queues begin with the word "w", and all dead letter queues begin with the "d", you could apply default configuration to those queues and reduce the chance of forgetting important configuration and having to migrate again in future.

If doing it in RabbitMQ isn't an option, you could write a wrapper module for your Rascal configuration which did something similar.