Ответ вслух Senior Асинхронные паттерны обновлено

Отмена работы, когда клиент ушёл

Вопрос

Клиент закрыл соединение, а обработчик продолжает делать три запроса к внешним API и тяжёлый запрос к БД. Как организуете отмену?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Стандартный механизм отмены в Node это AbortController. На каждый запрос создаю контроллер и вызываю abort(), когда соединение закрылось раньше ответа.

Что должно прозвучать в ответе

  • Создаю `AbortController` на запрос и вызываю `abort()` по событию `close` у запроса или ответа

  • Передаю `signal` во все операции: `fetch`, клиенты БД и SDK, которые его поддерживают, `timers/promises`, свои функции

  • Объединяю сигналы: клиент ушёл или общий дедлайн (`AbortSignal.any([req, AbortSignal.timeout(ms)])`)

  • Для запросов к БД отмена на стороне сервера: `statement_timeout` или отмена запроса через драйвер, иначе БД продолжит работу

  • Проверяю `signal.aborted` между шагами долгих циклов и не начинаю новые шаги

  • Важно различать: отмена чтения безопасна, а уже начатую запись нужно довести или откатить транзакцией

Что могут спросить следом

  • Что делать с операцией, которая не поддерживает AbortSignal?
  • Как пробросить сигнал в NestJS-сервис?
  • Чем таймаут на стороне клиента отличается от statement_timeout?

Разбор

Стандартный механизм отмены в Node это AbortController. На каждый запрос создаю контроллер и вызываю abort(), когда соединение закрылось раньше ответа. Сигнал передаю во все операции, которые его понимают: fetch (undici), многие SDK, timers/promises, events.once, свои функции. Часто сигнал комбинирую с дедлайном через AbortSignal.any и AbortSignal.timeout, чтобы запрос не жил дольше разумного, даже если клиент ждёт. С базой отдельная история: отмена на клиенте не останавливает запрос на сервере БД, поэтому нужен statement_timeout или явная отмена запроса драйвером. В длинных циклах проверяю signal.aborted между шагами. И разделяю чтение и запись: чтение отменять безопасно, а запись либо доводится до конца, либо откатывается транзакцией, чтобы не оставить данные в половинчатом состоянии.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме