My node application and RabbitMQ server are running on docker.
That nodejs application have reconnect logic which works great when I gracefully restart RabbitMQ service by kill
command in RabbitMQ container or by sudo docker-compose restart -t 10 rabbitmq
which wait till 10 seconds before sending forcefull kill
singal to RabbitMQ service.
But when I forcefully restart RabbitMQ service by sudo docker-compose restart -t 0 rabbitmq
then reconnect logic does not work. lsof
command on nodejs app container does not show any connections.
var amqp = require('amqplib')
var appRoot = require('app-root-path')
var rabbitMQConfig = require(`${appRoot}/config`).rabbitmq
var winston = require(`${appRoot}/logger`)
var utils = require(`${appRoot}/utils`)
var util = require('util')
var rabbitMQController = require(`${appRoot}/controllers/rabbitMQController`)
var request = require('request-promise')
function getRabbitMQConnectionString(rabbitMQConfig) {
var connPrefix = rabbitMQConfig.prefix
if (rabbitMQConfig.authEnabled === true) {
var credentials = rabbitMQConfig.userName + ":" + rabbitMQConfig.password +"@"
connPrefix += credentials
connString = util.format(connPrefix +'%s:%s%s', rabbitMQConfig.host, rabbitMQConfig.port, rabbitMQConfig.vhost)
} else {
connString = util.format(connPrefix +'%s:%s%s', rabbitMQConfig.host, rabbitMQConfig.port, rabbitMQConfig.vhost)
}
return connString
}
var connString = getRabbitMQConnectionString(rabbitMQConfig)
var initializeRabbitMQ = async function(channel) {
await channel.assertExchange(rabbitMQConfig.exchange, 'direct', { durable: true })
await channel.assertQueue(rabbitMQConfig.queue, { durable: true })
var url = util.format('%s%s:%s/api/bindings/%s/e/%s/q/%s', rabbitMQConfig.httpPrefix, rabbitMQConfig.host, rabbitMQConfig.managementPort, encodeURIComponent(rabbitMQConfig.vhost), rabbitMQConfig.exchange, rabbitMQConfig.queue)
var options = {
"method": "GET",
"uri": url,
"headers": {
"Authorization": "Basic " + new Buffer(rabbitMQConfig.userName + ":" + rabbitMQConfig.password).toString("base64"),
},
'json': true,
'timeout': 15000
}
var result = await request(options)
// console.log('alok', result)
result.forEach(async function(item) {
await channel.unbindQueue(rabbitMQConfig.queue, rabbitMQConfig.exchange, item.routing_key)
})
rabbitMQConfig.source.forEach(async function(item) {
await channel.bindQueue(rabbitMQConfig.queue, rabbitMQConfig.exchange, item)
})
}
var connect = async function() {
var conn = await amqp.connect(connString)
var channel = await conn.createChannel()
await initializeRabbitMQ(channel)
rabbitMQController.processMessages()
return channel
}
var prepareExports = async function(exportsObj) {
try {
exportsObj["connection"] = connect()
var channel = await exportsObj["connection"]
channel.on('error', function(error) {
winston.error(utils.getLogString("rabbitmq_channel_error", "", "", error.stack))
})
channel.on('close', function() {
winston.error(utils.getLogString("rabbitmq_channel_close", "", "", ""))
prepareExports(exportsObj)
})
} catch (error) {
winston.error(utils.getLogString(arguments.callee.name, "", "", error.stack))
await new Promise((resolve) => {
setTimeout(resolve, 5000)
})
prepareExports(exportsObj)
}
}
prepareExports(module.exports)
What should be proper way to make it work even in case of forceful abrupt restart of RabbitMQ service?