松弛Webhook导致cls钩住请求上下文孤立mysql连接

松弛Webhook导致cls钩住请求上下文孤立mysql连接,mysql,node.js,express,slack-api,cls-hooked,Mysql,Node.js,Express,Slack Api,Cls Hooked,主要问题: 我们有一个可爱的小express应用程序,它几个月来一直在压榨它,没有任何问题。我们通过按需打开一个连接来管理数据库连接,然后使用库“按请求”缓存它。在请求结束时,我们释放连接,这样我们的连接池就不会用完。经典经过几个月的时间和多次的联系,我们从未“泄露”过联系。直到现在!进入。。。松弛的我们使用slack事件处理程序,如下所示: app.use('/webhooks/slack', slackEventHandler.expressMiddleware()); 我们有点像其他任何

主要问题: 我们有一个可爱的小express应用程序,它几个月来一直在压榨它,没有任何问题。我们通过按需打开一个连接来管理数据库连接,然后使用库“按请求”缓存它。在请求结束时,我们释放连接,这样我们的连接池就不会用完。经典经过几个月的时间和多次的联系,我们从未“泄露”过联系。直到现在!进入。。。松弛的我们使用slack事件处理程序,如下所示:

app.use('/webhooks/slack', slackEventHandler.expressMiddleware());
我们有点像其他任何请求一样考虑它,但是松弛请求似乎与我们的cls钩住的用法玩得很奇怪。例如,我们使用node ts和nodemon在本地运行我们的应用程序(例如,您更改代码,应用程序将自动重新启动)。每次应用程序在我们的开发人员机器上本地重新启动,并且您尝试玩slack事件时,突然,当我们释放连接的中间件尝试这么做时,它认为会话中没有任何内容。然后使用普通端点时。。。它工作得很好,基本上看起来又恢复了正常工作状态。我们现在害怕使用slack集成进行prod,因为我们担心slack“请求”会耗尽连接池

背景

我们package.json的相关子集:

使cls连接会话的中间件

释放连接的中间件

按需创建连接并将其存储在“会话”中的代码

首先设置会话的代码

如果你走到这一步,恭喜你。感谢您的帮助


旁注:你不能付钱让我写一个更混乱的标题…

明白了!我们似乎已经在slack API的节点版本中发现了以下行为(似乎只发生在mac电脑上……有时)

问题是,这是在express应用程序的上下文中,因此Slack正在管理自己的事件处理程序系统与express的http端之间的接口(例如,返回200、500或其他)。所以似乎发生的是

// you have some slack event handler
slackEventHandler.on('message', async (rawEvent: any) => {
  const i = 0;
  i = i + 1;
  // at this point, the http request has not returned 200, it is "pending" from express's POV
  await myService.someMethod();
  // ^^ while this was doing its async thing, the express request returned 200.
  // so things like res.on('finished') all fired and all your middleware happened
  // but your event handler code is still going
});
因此,我们最终创建了一个手动调用来释放slack事件处理程序中的连接。奇怪

import { session } from '../db';

const context = (req, res, next) => {
  session.run(() => {
    session.bindEmitter(req);
    session.bindEmitter(res);
    next();
  });
};

export default context;
export const dbReleaseMiddleware = async (req, res, next) => {
  res.on('finish', async () => {
    const conn = session.get('conn');
    if (conn) {
      incrementConnsReleased();
      await conn.release();
    }
  });
  next();
};
  const poolConn = await pool.getConnection();
  if (session.active) {
    session.set('conn', poolConn);
  }
  return poolConn;
export const session = clsHooked.createNamespace('our_company_name');
// you have some slack event handler
slackEventHandler.on('message', async (rawEvent: any) => {
  const i = 0;
  i = i + 1;
  // at this point, the http request has not returned 200, it is "pending" from express's POV
  await myService.someMethod();
  // ^^ while this was doing its async thing, the express request returned 200.
  // so things like res.on('finished') all fired and all your middleware happened
  // but your event handler code is still going
});