macOS sleep mode causes AbortError: Redis connection lost and command aborted. It might have been processed.
See original GitHub issue@BridgeAR The error full stack trace was
[Sat Apr 15 2017 16:20:08 GMT+0200 (CEST)] Error:
AbortError: Redis connection lost and command aborted. It might have been processed.
at RedisClient.flush_and_error (/webservice/node_modules/redis/index.js:357:23)
at RedisClient.connection_gone /webservice/node_modules/redis/index.js:659:14)
at RedisClient.on_error (/webservice/node_modules/redis/index.js:405:10)
at Socket.<anonymous> (/webservice/node_modules/redis/index.js:279:14)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at emitErrorNT (net.js:1278:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9)
My question here if there is a recovery procedure to restore the connection as soon as the network become stable again.
Two cases when this error is generated are
-
You run the redis over a VPN and the VPN connection goes away and then back - see https://github.com/NodeRedis/node_redis/issues/1216
-
You are testing your backend, your local computer enters SLEEP mode: when you return from sleep energy saving mode, and try to connect to your service, redis will return this error, even if your network connection was up: is this due to a active connection put in “hold” by redis (?).
Supposed that we are in the second case (local computer in sleep mode), how to recover for sleep mode in the redis client?
My default retry strategy was:
retry_strategy: function (options) {
self.logger.warn("RedisStore.retryStragegy %@", options);
if (options && options.error && options.error.code === 'ECONNREFUSED') {
// End reconnecting on a specific error and flush all commands with a individual error
return new Error('The server refused the connection');
}
if (options && options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands with a individual error
return new Error('Retry time exhausted');
}
if (options && options.times_connected > 10) {
// End reconnecting with built in error
return undefined;
}
// the reconnect retry will happen exactly after this time in milliseconds
return Math.max(options.attempt * 100, 3000);
}
and I have this setup:
{
/** key default expire */
expire: 60 * 60 * 24,
/**
* If set to true, the keep-alive functionality is enabled on the underlying socket.
*/
socket_keepalive : true
}
My strategy was then this
function handleError(results,error) {
if( error && (error.code == 'NR_CLOSED' || error.code == 'UNCERTAIN_STATE')) { // connection closed, try reconnect
self._initRedisStore()
.then(ok=> { // store connected
if(results) return resolve(results);
else return execute(params,resolve,reject);
})
.catch(error => { // store connect error
if(results) return resolve(results);
else return execute(params,resolve,reject);
});
} else if( error && (error.code == 'ETIMEDOUT')) { // timed out
return execute(params,resolve,reject);
} else {
self.store.unset(cacheKey)
.then(result => {
return execute(params,resolve,reject);
})
.catch(error => { // store unset ERROR
return execute(params,resolve,reject);
});
}
}
when _initRedisStore
re-initialize the store when the error code was NR_CLOSED
or NR_CLOSED
. Shall I have to consider a ETIMEDOUT
here as well? I have not used it there, since in case of host computer sleep I thought the error should have been a connection close error, not a timeout error, that should happen when a active connection timed out.
Does it makes sense to handle this error as a ETIMEDOUT
for a dangling connection when the host is exiting the sleep mode?
Issue Analytics
- State:
- Created 6 years ago
- Comments:6 (3 by maintainers)
No, I suggest you modify your
retry_strategy
to always return a number. The number will be the time in milliseconds until redis is going to try to reconnect again.Yes, even though you will not receive a error message in that case that the connection was lost. But you could add a individual logger in there as well and still return a number.