| We use RMQ for most of our asynchronous processing. In most cases, we get a HTTP call and publish a message to the RMQ after committing the DB transaction, then we send the response to the HTTP client. We found out the hard way that RMQ does not behave like a transactional DB. Just because publishing worked does not mean the message will be delivered. Our solution is to also write the message into an outbox table in the DB.
We then publish the message using confirms[0]. RMQ asynchronously sends us a confirmation when it has really persisted the message.
We then delete the outbox entry. If we do not receive the confirmation in time, a timer will re-publish the message. Therefore I disagree with the suggestion of using a library wrapping the native RMQ one. We are using spring-amqp and this made it harder to understand what is going on. In the end, for a large project you will have to understand nuances of RMQ (and other infrastructure you are using). Using a leaky abstraction over it means you now have to understand both the underlying product and the abstraction. [0] https://www.rabbitmq.com/confirms.html#publisher-confirms |
1) Adopt RabbitMQ without any experts on the team 2) Conceal Rabbit/AMQP functionality as much as possible behind a simplifying abstraction, often in multiple layers, often written by non-experts 3) Run into some intractable reliability or scaling problem 4) Have no idea how to solve it because you still don't have any experts 5) Throw a lot of money at the problem, fail 6) Decide to do a very expensive migration to a different system (SNS+SQS, Kafka, etc.)
At that point, you go back to step 1. If you're lucky, somebody has expertise in the new system and the migration can be pulled off successfully. Otherwise, you either end up repeating the whole process or everything goes off the rails when you're halfway migrated to the new system.
This same process happens for all kinds of stuff, not just RabbitMQ, of course.