Implementamos um retry_strategy que emite um erro após uma certa quantidade de tentativas. Isso então faria um balão para o manipulador on ('erro') do Redis ser registrado e sair do aplicativo. Ao atualizar nossa biblioteca redis de 2.4.2
para 2.6.2
, notamos que esse comportamento não é mais o mesmo.
Caso Repro:
const redis = require('redis');
const MAX_ATTEMPTS = 10;
var client = redis.createClient(port, host, {
retry_strategy: redisRetryStrategy
});
client.on('error', onError);
function OnError(err) {
console.log(err);
throw new Error('SHUTDOWN THE APP, REDIS IS NOT RESPONDING??');
}
function redisRetryStrategy(host, options) {
if (options.attempt >= MAX_ATTEMPTS) {
// Stop reconnecting after reaching the maximum number of attempts
return new Error('Maximum redis reconnect attempts reached');
}
return 1000; // Schedule next reconnection attempt after 1 sec.
}
Na verdade, isso foi feito de propósito. A razão é que você já tem a informação de que o cliente falhou, então não precisa mais ser emitida. Esta não é, de fato, uma boa mudança em relação a manter o semver acordado: / Sinto muito por isso.
Eu gostaria de fazer uma pequena enquete para ver o que outras pessoas estão pensando. Ping @ NodeRedis / contributors @dirkbonhomme
Sim: borbulhe o erro para o listener de erro
Não: mantenha a solução atual
Apenas para oferecer um caso de uso em favor do anterior, o connect-redis fornece uma opção logErrors
que se torna (não obviamente) mutuamente exclusiva com retry_strategy
se os erros não surgirem.
new RedisStore({
logErrors: (err) => console.error, // does nothing
retry_strategy: (options) => {
if (options.error.code === 'ECONNREFUSED' || options.error.code === 'ENOTFOUND') {
return new Error('The server could not be found or refused the connection');
}
return 1000;
}
})
@tj
Acho que a funcionalidade atual está bem, contanto que esteja na documentação, o que não está. Acho que também seria aceitável adicionar uma opção que ainda gerasse erros retornados da estratégia de nova tentativa.
Ex.:
redis.createClient({
retry_strategy: ...,
retry_strategy_bubble_up: true or false (default to false to keep existing functionality)
});
Passei o último dia tentando descobrir por que os erros não estavam sendo registrados. Agora que o registro está no retorno de chamada retry_strategy, tudo está como eu quero em meu aplicativo.
Em vez de lançar o erro, estou emitindo manualmente o evento de erro que pode ser detectado pelo manipulador de erros:
retry_strategy: function(options) {
logger.debug('Retry redis connection: ', options.attempt);
// 5 mins
if (options.total_retry_time > 1000 * 60 * 5) {
// End reconnecting after a specific timeout and flush all commands with a individual error
return logger.error('Redis: maximum retry time exhausted');
}
if (options.attempt > 5) {
// End reconnecting with built in error
logger.error('Redis: maximum connection retry reached');
return client.emit('error', 'maximum retry');
}
return 1000 * 2;
},
Bubble up! (ou outra coisa)
O emissor de erro customizado como @alannesta escreveu é bagunçado, retry_strategy
é um dos parâmetros do construtor, ele não deve acessar objetos que estejam fora da função.
NodeRedis
já tinha um sistema de eventos, basta usá-lo!
Como end
foi retirado e significa "conexão encerrada", podemos adicionar um novo evento (vamos chamá-lo de "desligamento" por enquanto) indicando "fizemos tudo o que podíamos, esta conexão morreu , a partir de agora não faremos nada sobre isso, é melhor vocês fazerem uns trabalhos de limpeza ”.
Eu realmente preciso dessa mudança.
Aconteceu alguma coisa com esse problema?
Existe uma razão para isso não ser corrigido ou apenas prioritário? Qual é a vantagem de não emitir o evento? Não existe uma maneira óbvia de encerrar um serviço sem mais conexão redis funcional ao usar retry_strategy
e esse deve ser um caso de uso bastante básico. A melhor solução, entretanto, provavelmente seria um evento separado, como @AaronJan sugeriu.
Eu lancei a v3.0.0 que agora borbulha qualquer erro retornado de retry_strategy
até o ouvinte de evento error
.
Comentários muito úteis
Sim: borbulhe o erro para o listener de erro