You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest在Travis-CI中检测到Redis客户端未关闭及连接方法缺失问题

问题排查与解决方案

问题1:redisClient.connect 不是函数

根因

Node Redis 包存在版本不兼容:

  • 本地安装的是4.x及以上版本,该版本引入了connect()异步方法,配置项也采用socket层级结构
  • Travis CI 环境因node_modules缓存、未指定版本安装redis,实际拉取到的是3.x及以下版本,该版本客户端没有connect()方法,创建客户端时会自动发起连接,配置结构也和4.x版本不通用

解决步骤

  • 清理Travis项目的node_modules缓存,避免旧版本包残留
  • 修改.travis.yml的install步骤,指定安装和本地一致的redis兼容版本,示例:
    install:
      - npm i
      - npm i redis@4.6.7 # 替换为你本地实际使用的redis版本号即可
    
  • 可在install步骤新增npm list redis命令打印实际安装的redis版本,方便后续排查确认

问题2:Jest检测到开放TCP句柄无法退出

根因

两种场景都会触发该问题:

  1. 若Travis环境安装的是3.x版本redis,创建客户端时就会自动发起TCP连接,哪怕连接失败,底层socket句柄也不会自动销毁,会一直挂载在事件循环中
  2. 就算使用4.x版本,你当前的代码只捕获了连接异常,没有主动销毁不可用的客户端,残留的重连逻辑也会持续持有句柄

解决步骤

  1. 先按问题1的方案固定redis版本,消除环境版本差异
  2. 修改Redis初始化逻辑,连接失败时主动销毁客户端:
async function getClient() {
  const redisClient = createClient({
    socket: {
      url: redisConfig.connectionString,
      reconnectStrategy: (currentNumberOfRetries: number) => {
        if (currentNumberOfRetries > 1) {
          // 重连超限后返回false停止重连,不要直接抛错
          return false;
        }
        return 1000;
      },
    },
  });
  try {
    await redisClient.connect();
  } catch (e) {
    console.log(e);
    // 连接失败主动断开销毁客户端,释放句柄
    await redisClient.quit().catch(() => redisClient.disconnect());
    throw e; // 向上抛出错误,避免上层拿到不可用的客户端实例
  }
  return redisClient;
}
  1. 在Jest测试集的afterAll钩子中,主动关闭所有持有的Redis连接:
afterAll(async () => {
  if (redisClientInstance) { // 替换为你实际持有的redis客户端变量
    await redisClientInstance.quit().catch(() => redisClientInstance.disconnect());
  }
})
  1. 临时兼容方案:如果仅需要CI快速跑通测试,可在jest启动命令后添加--forceExit参数,强制Jest测试完成后退出进程,该方案更推荐仅作为临时兜底使用。

内容的提问来源于stack exchange,提问作者Jia Cheng Sun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:00:00