Post mortem: cледи за middleware или как мы сломали комментарии

в 12:15, , рубрики: node.js, nodejs, post mortem, vuejs, баги, Блог компании ТechMedia, мобильная версия, Разработка веб-сайтов, хабр

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

Post mortem: cледи за middleware или как мы сломали комментарии - 1

Суть проблемы: человек отправляет комментарий к посту, видит его со своим логином и уходит со страницы, но если обновить страницу, этот комментарий будет уже под другим именем пользователя. Это работало только в случае, если пользователи одновременно находились на странице одного поста.

По нашим данным, за выходные с мобильной версии было отправлено 774 комментария. Каждый из них мог пострадать.

Немного технических подробностей

Мы используем связку VueJS + NodeJS (Express, SSR).

NodeJS обслуживает в один поток асинхронно сразу множество соединений, то есть использует один инстанс на всех клиентов. Это значит, что глобальные переменные инициализируются только один раз и живут до тех пор, пока жив инстанс.

Поэтому необходимо крайне внимательно относиться к порядку выполнения middlewar'ов, а также к определению и переопределению значений переменных (особенно, если они глобальные).

И вот что с нами случилось (это пример кода):

global.foo = 'bar';

app.get('/main', (req, res, next) => {
  res.send(global.foo);
});

app.get('/change', (req, res, next) => {
  global.foo = global.foo === 'bar' ? 'barbar': 'bar';
  res.send(global.foo);
});

Что вернёт сервер?

  • Клиент 1 на /main >>> ‘bar’
  • Клиент 2 на /change >>> ‘barbar’
  • Клиент 1 снова на /main >>> ‘barbar’

Пример, конечно, сильно упрощенный, но принцип тот же.

Сейчас всё работает как нужно. Простите, пожалуйста, за неудобства и, если вас затронула такая проблема, обратитесь к нам через форму обратной связи.

Мы ищем возможность вернуть комментарии их законным владельцам, расскажем, что из этого получилось позже.

Автор: de_arnst

Источник

* - обязательные к заполнению поля