Closed rhyslbw closed 6 years ago
I ran into this same problem as well. It appears that this module makes an assumption:
RabbitMQ will be running when rabbot tries to connect.
This is not the case with docker-compose.
To fix this, I did two things, after getting the connected
event from rabbot
. It is a bit hacky, but it appears to work:
let rabbit = require("rabbot")
let connectionConfig = {
//connection details
};
rabbit.addConnection(connectionConfig) //Start by adding the connection only
rabbit.on("connected", function(a, b) {
//Once we've connected, replace the connection promise with one that automatically resolves
//Prior to this change, this is the original promise that failed. Publishing will always fail because of this.
rabbit.connections[connectionConfig.name].promise = new Promise(function (resolve, reject) {
resolve()
})
//Now reconfigure rabbit because if it fails its initial connection, the configuration doesn't ever get setup
rabbit.configure({
connection: connectionConfig,
exchanges: [],
queues: [],
bindings:[]
})
})
Not 100% that using the built-in Promise
will cause any issues with the promises used in this project.
P.S. I looked at trying to fix this inside the module and submitting a PR, but I think it will require someone that better understands the internals to address. It might require a bit of re-working the internals from the bit of time I spent nailing down what was going on.
You can get rabbot to keep retrying by catching the failure and telling it to just start over. You can also tell it to increase the number of times it will attempt to connect to a broker before considering the broker "failed".
See the retryLimit
and failAfter
settings here to change failure semantics.
See this on telling it to reset and try again after reaching failure.
I had the same issue.
It is true that more attempts to connect will be made but the promise returned by configure
is rejecting on the first failed attempt.
I ended up doing this
const rabbot = require('rabbot');
const Promise = require('bluebird');
async function connect() {
await rabbot.configure({
connection: {
/* connection details */
retryLimit: 0, // no implicit retries
},
/* other options */
});
// Update internal promise - see @edorsey code
const connectionName = 'default';
rabbot.connections[connectionName].promise = Promise.resolve();
}
async function connectWithRetry(attempts = 1) {
try {
await connect();
} catch (err) {
if (attempts < 5) {
console.log('Connection to RabbitMQ failed. Retrying in 5s...');
await Promise.delay(5000);
return connectWithRetry(attempts + 1);
}
throw err;
}
}
try {
await connectWithRetry();
} catch (err) {
console.error(err);
process.exit(1);
}
@antmarot When I tried your code I received a UnhandledPromiseRejectionWarning when the connection is unreachable and the code exits. There's not a catch block on the configure promise, but I've had no luck adding one and making this work. Any insight would be appreciated.
~@genemyers I added a snippet calling the connection logic. Hope this helps.~
@genemyers I ran into the same issue. I had to use the fix proposed by @edorsey. The code in my previous response has been adapted.
@antmarot would you be so kind as to provide a single module that demonstrates your solution? I am getting an error that Promise.delay isn't a function.
@genemyers I now included the module dependencies. Promise.delay
is provided by bluebird
.
@antmarot I should have caught that, thanks, working now.
See reproduction here: https://github.com/rhyslbw/rabbot-configure-docker
Context Two services in a docker-compose file, a rabbot client using the
configure
api to connect to a rabbitmq:3-management broker in the stack via the default network.Problem When bringing up the stack via
docker-compose up
only the default response topology is created after the connection is established. When the client service is run independently on my dev machine with ports mapped into the broker, it connects and configures the defined topology as expected.Notes
default.connection.configured
event is never fired