To simplify my problem, I have
App1 with @Transactionnal method createUser():
- Insert new user in database
- Add async message in RabbitMQ so that the user receives a notification mail
- (potentially some additional code, but not much)
App2 with RabbitMQ message consumer
- Consumes messages on the mailing queue in real-time
- Read mail data in database
- Send mail
The problem is that sometimes, App2 tries to consume the RabbitMQ message before the transaction is even committed on App1. This means that App2 can't read the mail data on database because the user is not yet created.
Some solutions may be:
- Use READ_UNCOMMITED isolation level on App2
- Add some delay in RabbitMQ messages delivery (or some RetryTemplate on the consumer)
- Change the way we send emails...
I've seen there is a RabbitTransactionManager in Spring, but I can't understand how it is supposed to work. Internals of transaction handling stuff has always seemed to be a bit hard to understand and the documentation doesn't help so much either.
Is there a way to do something like this?
- Add a message to a RabbitMQ queue in a @Transactionnal method
- When the transaction ends, the message is committed to the queue, and the changes are committed to the database
- So that the message can't be consumed before the DB transaction ends
How? And what to expect for example if I send synchronous RabbitMQ messages instead of asynchronous messages? Would it block the thread waiting for a response or something? Because we do send sync and async messages for different usecases.