Created by: gmauricio
On client initialization, Bull waits for the Redis client connection to be 'ready' before trying to send commands to it. In order to do so, it keeps a promise that only resolves after the Redis client emits a 'ready' event. It also listens for 'error' events, if an error comes, initialization fails.
However, having an error reported from Redis client, should not fail initialization immediately, because Redis client can retry the connection. Initialization should not fail on the first error it sees, but instead wait for the client to give up on reconnecting. That's why here I'm changing from listening to 'error's and instead listen to an 'end' event, which signals that the client won't try to reconnect anymore or that it failed to establish a connection to the server. See Connection Events.
For context, what I'm trying to fix is situations where a queue is instantiated before Redis server is ready, causing the instance to stay in a broken state (_initializing promise rejected and unrecoverable), even when the client is able to connect later, thanks to ioredis
"auto-reconnect" feature.
I didn't remove the error listener entirely, it is still useful to keep track of seen errors, so when the 'end' occurs we have some information on why the connection failed, by exposing that last seen error when rejecting initialization promise.
Note: for testing, I passed a retryStrategy
that always returns false, so no retries are made. By default ioredis
will retry forever. This means that bull users should pay extra care on connection error handling and probably play with retryStrategy
option, for example to limit the number of retries. This will change expected behavior, since before this, calling isReady
on a queue where the connection could not be immediately established resulted in a error, but now, by default, it won't crash but hold indefinetely until a connection can be established, unless number of retries are limited.