Вялые веб-зацепки приводят к тому, что cls-hooked контекст запроса теряет связь с mysql - PullRequest
3 голосов
/ 14 апреля 2020

Основная проблема: У нас есть прекрасное маленькое express приложение, которое уже несколько месяцев ломает его без проблем. Мы управляем нашими соединениями с БД, открывая соединение по требованию, но затем кэшируем его «по запросу», используя библиотеку cls-hooked . По окончании запроса мы освобождаем соединение, чтобы наш пул соединений не заканчивался. Classi c. В течение нескольких месяцев и многих связей мы никогда не «просачивались». До настоящего времени! Введите ... расслабиться! Мы используем обработчик событий Slack следующим образом:

app.use('/webhooks/slack', slackEventHandler.expressMiddleware());

и мы вроде думаем об этом , как и любой другой запрос, однако запросы Slack выглядят странно с нашим использованием cls-hooked , Например, мы используем node-ts и nodemon для локального запуска нашего приложения (например, при изменении кода приложение перезапускается автоматически). Каждый раз, когда приложение перезапускается локально на наших компьютерах разработчиков, и вы пытаетесь поиграть со слабыми событиями, внезапно, когда наше промежуточное ПО, которое освобождает соединение, пытается это сделать, оно думает, что в сеансе ничего нет. Когда вы затем используете нормальную конечную точку ... она работает нормально и, по-видимому, сбрасывает снова работает нормально. Теперь мы боимся go, чтобы продолжать нашу слабую интеграцию, потому что мы обеспокоены тем, что наши слабые "запросы" приведут к истощению нашего пула соединений.

Фон

Соответствующее подмножество нашего пакета. json:

{
  "@slack/events-api": "^2.3.2",
  "@slack/web-api": "^5.8.0",
  "express": "~4.16.1",
  "cls-hooked": "^4.2.2",
  "mysql2": "^2.0.0",
}

Промежуточное программное обеспечение, которое делает сеанс cls-hooked

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');

Если вы получили это далеко Поздравляю. Любая помощь приветствуется!

Примечание: вы не можете заплатить мне, чтобы написать более запутанный заголовок ...

1 Ответ

0 голосов
/ 15 апреля 2020

Разобрался! Кажется, мы определили следующее поведение в версии узла API slack (похоже, это происходит только на компьютерах ma c ... иногда )

Проблема заключается в том, что контекст приложения express, поэтому Slack управляет интерфейсом между собственной системой-обработчиком событий + стороной http с помощью express (например, возвращает 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
});

Итак, мы закончили тем, что создали ручной вызов для освобождения соединений в наших обработчиках слабых событий. Weird!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...