NodeJS Redis - 在后台重新连接

NodeJS Redis - Reconnect In Background

我的情况是 - 我正在尝试通过 REDIS 密钥检索资源。如果密钥不存在,则从 API.

获取它

运行 遇到以下问题:如果 Redis 连接断开或者我无法从启动时连接到 Redis,则 nodejs 库 ('redis') 将继续尝试重新连接。它阻止我通过 API 获取我需要的信息,因为重试逻辑将接管并且不会继续获取所需信息。

我想在后台使用此功能 运行 - 可以吗?

意思是,如果 Redis down/cannot 从 NodeJs 连接到 REDIS,那么它将尝试重新连接。然而,当它关闭并且应用程序将尝试定期重新连接时,我希望能够通过备份计划获取数据,即通过 API,如上所述。

任何关于这种情况的指示都将不胜感激 - 提前致谢。

您可以在 redis-connection 周围创建一个 wrapper/proxy,确保所有 redis 操作都已连接到 redis。如果不是,你可以抛出一个错误(你可以在调用者中处理)或者 return undefined.

基本上,您可以监听 readyerror 事件并更新包装器内的 status 标志,以便始终了解当前连接状态。

现在,这肯定会涵盖初始连接不成功或呼叫之间发生断开连接的情况。问题是在您成功检查 status 标志后断开连接的罕见情况。要解决这个问题,您可以为 redis 调用定义一个最大等待时间,如果达到超时则 return/throw 一个错误并忽略 redis 结果。下面是一些可以帮助您入门的基本代码:

class RedisService {
    isConnected = false;
    client;

    constructor() {
        this.client = redis.createClient();
        this.client.get = promisify(this.client.get).bind(this.client);
        this.client.set = promisify(this.client.set).bind(this.client);
        this.attachHandlers();
    }

    attachHandlers() {
        this.client.on("ready", () => {
            this.isConnected = true;
        });           
        this.client.on("error", (err) => {
            this.isConnected = false;
            console.log(err);
        });
    }

    async tryGet(key) {
        if (!this.isConnected) {
            return undefined; // or throw an error
        }
        return Promise.race([this.client.get(key), this.wait()]);
    }

    async trySet(key, val) {
        if (!this.isConnected) {
            return undefined; // or throw an error
        }
        return Promise.race([this.client.set(key, val), this.wait()]);
    }

    wait(ms = 200) {
        return new Promise(resolve => {
            setTimeout(resolve, ms);
        })
    }
}

然后在你的来电者中你可以这样做:

async someMethodThatCallsRedisOrApi() {
    let result;
    try {
        result = await redisService.tryGet('testkey');
    } catch (e) {
        console.log(e);
    }
    if (!result) {
        result = apiService.get(...); // call the actual api to get the result
        await redisService.trySet('testkey', result);
    }
    res.json(result)
});