Closed AllanDaemon closed 3 years ago
Hi @AllanDaemon,
Given a process that is just publishing to RabbitMQ, how to close it gracefully, in order that all the messages send to be published to be sent instead of lost?
You need to have some mechanism (e.g. outstanding) for monitoring inflight messages, and preventing shutdown until all have been successfully published by the success
event and absence of a return
event..
broker.publish('p1', 'some message', (err, publication) => {
if (err) throw err; // publication didn't exist
publication
.on('success', (messageId) => {
console.log('Message id was: ', messageId);
})
.on('error', (err, messageId) => {
console.error('Error was: ', err.message);
})
.on('return', (message) => {
console.warn('Message was returned: ', message.properties.messageId);
});
});
'return' events should be emitted first, but because 'success' indicates that the message was successfully delivered to the broker, you will still get a 'success' event even when a message is unrouteable.
However, this does not necessarily guarantee that you will never lose messages. Your application could still crash or be rudely killed while messages are in progress. You cannot resolve through RabbitMQ alone - you need a detection and recovery mechanism built into your wider systems architecture.
To give a little more context as to why Rascal shouldn't keep track of outstanding messages when publishing, imagine the following scenario...
If Rascal refused to shutdown while there are outstanding messages, it could stop half way through the workflow during step 3, therefore you need to rely on monitoring the outstanding work independently of Rascal.
With this in mind are you OK to close?
Given a process that is just publishing to RabbitMQ, how to close it gracefully, in order that all the messages send to be published to be sent instead of lost?
To better explain it, here is a minimal version of the
.mjs
file that I'm using to test latency and found out the issue (The original is at the end of the post):If I run this code, it will close with no error, but just one or sometimes none of the published messages will get to the RabbitMQ.
If I remove the last line with the
await broker.shutdown()
, it will send all the messages to RabbitMQ but it will be kept running forever without exiting the process.I was looking for something like
await broker.finishSendingEverything()
thing, but I couldn't find anything alike (I tried looking in the documentation, Google, code in the repository, StackOverflow, etc).The main problem is that when the process has to be restarted, it cannot lose anything. Another thing I was looking for is a way to instead of waiting to send everything that is remaining, read and save them in another place and try to send it after I restart.
I tried to investigate the source code for that, but because of the encapsulation using closure for the
broker
in theBrokerAsPromised
, I can't do anything practically.So how to handle process closing without losing data?
Basic info
node
:v14.18.1
rascal
:13.1.0
Original file used to test (with latency measurements)