ToB企服应用市场:ToB评测及商务社交产业平台

标题: QueryFailedError: Connection Terminated [打印本页]

作者: 王海鱼    时间: 2023-5-16 10:03
标题: QueryFailedError: Connection Terminated
简单提一下这个问题,先讲思路,后面再进行深入的探索和解析和发散
事情发生在笔者开发某个typescript服务端项目的过程中。笔者需要将一个基于typeorm的读写数据库操作进行异步处理,也就是不阻塞当前线程。
大体是这样的一个行文:
  1. // 用于typeorm的models文件中
  2. class Person {
  3.     @Column({ nullable: true })
  4.     code: string | null = null;
  5.     async initCode() {
  6.         if (!this.code) return;
  7.         
  8.         this.code = randomAlphabet(); // 随机生成的code
  9.     }
  10. }
  11. // 读写数据库文件中, eg: repos/person.ts
  12. async function generateCode(person: Person): Promise<Person> {
  13.     try {
  14.         person.initCode();
  15.     } catch (e) {
  16.         // error catcher
  17.     }
  18. }
  19. // 处理逻辑的controllers中,eg: controllers/personController.ts
  20. async function generateCodeForPerson(ctx, next): Promise<void> {
  21.     const person = await getPerson(ctx.params.id);
  22.     void generateCode(person); // 这里不做await,选择异步处理
  23.     ctx.code = 200;
  24. }
复制代码
那么好,由于该项目比较重要,所以笔者所在项目组使用jest进行e2e测试,以确保api可用。同时会部署CI,用于在pull request过程中进行代码自测。
其中测试generateCode大致是这么一个走法:
  1. describe('testGenerateCode', async () => {
  2.     let runInBackgroundMock: jest.SpyInstance<
  3.         void,
  4.         [callback: () => Promise<unknown>]
  5.     >; // 这个是jest用于劫持运行函数中的函数后,将函数中的异步改同步的操作
  6.     beforeAll(async () => {
  7.         // 此处,将测试函数中所运行的utils.runInBackground方法进行mock,取消其异步性,将在未来笔记中深入讲解
  8.         runInBackgroundMock = jest
  9.             .spyOn(utils, 'runInBackground')
  10.             .mockImplementation();
  11.         initDB(); // 初始化CI过程中连接测试DB的Client,占用DB连接资源
  12.     })
  13.     /**
  14.      * 此处不止一个describe
  15.      */
  16.     describe('should successful', async () => {
  17.         await testGenerateCodeForPerson(); // 其中调用了generateCodeForPerson,但是比较深,所以当时没发现
  18.     })
  19.     afterAll(async () => {
  20.         closeDB(); // 关掉DBClient,释放DB连接资源
  21.     })
  22. });
复制代码
细心的读者应该能够但从中发现问题了:万一没执行完generateCode的内容,就closeDB了,那不就出问题了?
没错!笔者遇到这个问题了,但第一时间没有意识到问题来自笔者的代码,下面是CI的报错:

此处插入题外话,笔者发现CI执行每个e2e的测试文件的次序是固定的,走到generateCode的下一个e2e测试任务就马上会遇到该问题,以至于笔者一直以为是任务A出了问题,但本地单独jest该任务永远都是Pass的,致使笔者一度有些...
但是经过前辈的指导,其中一个就是让笔者在本地使用CI所使用的命令,对所有e2e测试文件进行测试,而不是对单个e2e测试文件进行测试。同时,前辈让笔者留意是否与DB之间的连接关闭之后仍然有着读写DB的操作。
也就是说:
  1. # 用这个
  2. yarn jest tests/e2e
  3. # 而不是用这个
  4. yarn jest tests/e2e/generate_code_for_person.ts
复制代码
得益于本地运行命令,笔者发现测试文件的执行顺序并不是固定的,自然而然地发现每一个跟在generateCode的后e2e测试任务就会QueryFailedError。于是进行了注释debug方法,也就是每个describe都注释一下,最后锁定了问题出在generateCode函数中。
由此,笔者悻悻地将代码给改了,给controllers/personController.ts中加了一个utils.runInBackground。
也就是:
  1. // 处理逻辑的controllers中,eg: controllers/personController.ts
  2. async function generateCodeForPerson(ctx, next): Promise<void> {
  3.     const person = await getPerson(ctx.params.id);
  4.     utils.runInBackGround(async () => {
  5.         await generateCode(person); // 这里做不做await好像都没所谓了。
  6.     });
  7.     ctx.code = 200;
  8. }
复制代码
于是乎就这么改了,CI就过了。
所以后续会继续记录在进行和使用jest、postgres sql、typeorm、数据库表设计过程中的的所见所闻。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4