【问题标题】:Close redis connection when using NestJS Queues使用 NestJS 队列时关闭 redis 连接
【发布时间】:2020-11-08 12:12:05
【问题描述】:

我正在尝试在 NestJS 项目中设置 E2E 测试,但是,jest 输出如下所示:

Jest did not exit one second after the test run has completed

经过大量阅读,这是因为有一些资源尚未释放,经过一些调试后,它打开了由ioredis 创建的redis 的开放连接,bull 使用该连接,NestJS 使用它来执行任务队列处理。问题是我在测试代码中没有对连接的引用,那么我该如何关闭它呢?我正在像这样在afterAll jest 的钩子中拆除 Nest 应用程序:

  afterAll(async () => {
    await app.close();
  });

但它什么也没做,连接仍然存在,并且开玩笑的错误消息仍然存在。我知道我可以将--forceExit 添加到jest 命令中,但这并不能解决任何问题,只是将问题隐藏在地毯下。

【问题讨论】:

  • 解决了这个问题吗?我遇到了同样的问题,在使用--detectOpenhandles 后我意识到ioredis StandaloneConnector 有一个tcp 连接打开

标签: testing redis jestjs nestjs ioredis


【解决方案1】:

这花了我一段时间才弄清楚。您需要在 afterAll 挂钩中关闭模块。我可以通过查看 nestJS Bull 存储库中的测试找到这一点。

describe('RedisTest', () => {
  let module: TestingModule;
  beforeAll(async () => {

    module = Test.createTestingModule({
      imports: [
        BullModule.registerQueueAsync({
          name: 'test2',
        }),
      ],

    });
  });

  afterAll(async () => {
    await module.close();
  });
});

https://github.com/nestjs/bull/blob/master/e2e/module.e2e-spec.ts

【讨论】:

    【解决方案2】:

    在几乎陷入抑郁的挣扎之后,我找到了一个对我有用的解决方案。
    我正在使用"@nestjs/bull": "^0.3.1""bull": "^3.21.1"
    由于来自bul 包的队列使用redis,因此尽管模块和应用程序已关闭,但它仍保持连接打开。

        await moduleRef.close();
        await app.close();
    

    我意识到,当使用--detectOpenHandles 同时依赖leaked-handles 库获取更多信息时,您会在控制台中看到类似这样的内容:

        tcp stream {
           fd: 20,
           readable: true,
           writable: false,
           address: {},
           serverAddr: null
        }
    
        tcp handle leaked at one of: 
        at /media/user/somePartitionName/Workspace/Nest/project- 
        name/node_modules/ioredis/built/connectors/StandaloneConnector.js:58:45
        tcp stream {
           fd: 22,
           readable: true,
           writable: true,
           address: { address: '127.0.0.1', family: 'IPv4', port: 34876 },
           serverAddr: null
        }
    
    

    解决方案 使用beforEach() & afterEach()

    • beforEach() 中,添加此指令以获取队列实例:
        queue = moduleRef.get(getQueueToken("queuename"));
    
    • afterEach() 中,像这样关闭队列:(同时关闭您的应用和模块以便更好地练习)
        await queue.close();
    

    注意

    使用 beforAll()afterAll() 不起作用,并且发生同样的问题,至少从我尝试过的情况来看,beforEach()afterEach() 结合使用。

    【讨论】:

    • 现在的问题是,您正在为每个测试分配和关闭连接,似乎您泄漏了连接或代码效率低下(泄漏周期),谢天谢地,我没有接触 nodejs再次(我知道不是nodejs的错,但仍然如此)。
    猜你喜欢
    • 2022-11-07
    • 2020-09-19
    • 1970-01-01
    • 2014-04-18
    • 2020-05-09
    • 1970-01-01
    • 2013-08-31
    • 2022-06-16
    • 1970-01-01
    相关资源
    最近更新 更多