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

AsyncLocalStorage для контекста запроса

Вопрос

Нужно, чтобы каждая строка лога внутри обработки запроса содержала requestId, не передавая его аргументом через все функции. Какой механизм Node для этого предназначен?

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

Выберите вариант, и откроется разбор.

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

Коротко

Правильный ответ: AsyncLocalStorage из node:asynchooks: контекст переживает await. AsyncLocalStorage.run(store, fn) делает store доступным через getStore() во всём, что асинхронно порождено из fn, включая продолжения после await.

Варианты ответа

  1. Глобальная переменная, которую middleware перезаписывает на каждом запросе
  2. process.env.REQUEST_ID, который middleware выставляет перед обработчиком
  3. worker_threads: отдельный поток на запрос со своими глобальными
  4. AsyncLocalStorage из node:async_hooks: контекст переживает awaitправильный ответ

Разбор

AsyncLocalStorage.run(store, fn) делает store доступным через getStore() во всём, что асинхронно порождено из fn, включая продолжения после await. На этом построены трейсинг OpenTelemetry, контекст в pino-http, nestjs-cls. Стабилен и широко используется.

Глобальная переменная и process.env общие для всех одновременных запросов: при конкурентной обработке запрос A запишет id, запрос B перезапишет, и логи A получат чужой id. Поток на запрос в Node это дорого и бессмысленно для I/O-нагрузки.

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

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

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