gpt4 book ai didi

javascript - Redis (ioredis) - 无法捕获连接错误以便优雅地处理它们

转载 作者:IT王子 更新时间:2023-10-29 06:12:26 28 4
gpt4 key购买 nike

我正在尝试优雅地处理 Redis 错误,以便绕过错误并改为执行其他操作,而不是让我的应用程序崩溃。

但到目前为止,我不能只捕获 ioredis 抛出的异常,它绕过了我的 try/catch 并终止了当前进程。当前的行为不允许我优雅地处理错误,也不允许我从替代系统(而不是 redis)获取数据。

import { createLogger } from '@unly/utils-simple-logger';
import Redis from 'ioredis';
import epsagon from './epsagon';

const logger = createLogger({
label: 'Redis client',
});

/**
* Creates a redis client
*
* @param url Url of the redis client, must contain the port number and be of the form "localhost:6379"
* @param password Password of the redis client
* @param maxRetriesPerRequest By default, all pending commands will be flushed with an error every 20 retry attempts.
* That makes sure commands won't wait forever when the connection is down.
* Set to null to disable this behavior, and every command will wait forever until the connection is alive again.
* @return {Redis}
*/
export const getClient = (url = process.env.REDIS_URL, password = process.env.REDIS_PASSWORD, maxRetriesPerRequest = 20) => {
const client = new Redis(`redis://${url}`, {
password,
showFriendlyErrorStack: true, // See https://github.com/luin/ioredis#error-handling
lazyConnect: true, // XXX Don't attempt to connect when initializing the client, in order to properly handle connection failure on a use-case basis
maxRetriesPerRequest,
});

client.on('connect', function () {
logger.info('Connected to redis instance');
});

client.on('ready', function () {
logger.info('Redis instance is ready (data loaded from disk)');
});

// Handles redis connection temporarily going down without app crashing
// If an error is handled here, then redis will attempt to retry the request based on maxRetriesPerRequest
client.on('error', function (e) {
logger.error(`Error connecting to redis: "${e}"`);
epsagon.setError(e);

if (e.message === 'ERR invalid password') {
logger.error(`Fatal error occurred "${e.message}". Stopping server.`);
throw e; // Fatal error, don't attempt to fix
}
});

return client;
};

我正在模拟一个错误的密码/url,以查看配置错误时 redis 的 react 。我已将 lazyConnect 设置为 true 以处理调用方的错误。

但是,当我将 url 定义为 localhoste:6379 (而不是 localhost:6379) 时,我收到以下错误:

server 2019-08-10T19:44:00.926Z [Redis client] error:  Error connecting to redis: "Error: getaddrinfo ENOTFOUND localhoste localhoste:6379"
(x 20)
server 2019-08-10T19:44:11.450Z [Read cache] error: Reached the max retries per request limit (which is 20). Refer to "maxRetriesPerRequest" option for details.

这是我的代码:

  // Fetch a potential query result for the given query, if it exists in the cache already
let cachedItem;

try {
cachedItem = await redisClient.get(queryString); // This emit an error on the redis client, because it fails to connect (that's intended, to test the behaviour)
} catch (e) {
logger.error(e); // It never goes there, as the error isn't "thrown", but rather "emitted" and handled by redis its own way
epsagon.setError(e);
}

// If the query is cached, return the results from the cache
if (cachedItem) {
// return item
} else {} // fetch from another endpoint (fallback backup)

我的理解是redis错误是通过client.emit('error', error)处理的,是async的,被调用者不抛出错误,调用者是不允许的使用 try/catch 处理错误。

是否应该以非常特殊的方式处理 Redis 错误?难道不能像我们通常处理大多数错误那样捕获它们吗?

此外,在抛出致命异常(进程停止)之前,redis 似乎重试了 20 次(默认情况下)连接。但我想处理任何异常并以我自己的方式处理它。

我已经通过提供错误的连接数据测试了 redis 客户端的行为,这使得无法连接,因为该 url 上没有可用的 redis 实例,我的目标是最终捕获各种 redis 错误并妥善处理它们。

最佳答案

连接错误 are reported as an error event在客户端 Redis 对象上。

根据"Auto-reconnect" section of the docs , ioredis 将在与 Redis 的连接丢失时自动尝试重新连接(或者,大概无法首先建立连接)。只有在 maxRetriesPerRequest 尝试之后,挂起的命令才会“因错误而刷新”,即到达此处的 catch:

  try {
cachedItem = await redisClient.get(queryString); // This emit an error on the redis client, because it fails to connect (that's intended, to test the behaviour)
} catch (e) {
logger.error(e); // It never goes there, as the error isn't "thrown", but rather "emitted" and handled by redis its own way
epsagon.setError(e);
}

由于您在遇到第一个错误时停止程序:

  client.on('error', function (e) {
// ...
if (e.message === 'ERR invalid password') {
logger.error(`Fatal error occurred "${e.message}". Stopping server.`);
throw e; // Fatal error, don't attempt to fix

...重试和随后的“错误刷新”永远没有机会运行。

忽略client.on('error'中的错误,你应该得到从await redisClient.get()返回的错误。

关于javascript - Redis (ioredis) - 无法捕获连接错误以便优雅地处理它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57445171/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com