Код-ревью: обработка ошибок в сервисе
Вопрос
Фрагменты обработки ошибок из Node-сервиса. Найди, что приведёт к потере ошибок, падению или некорректной работе.
process.on('uncaughtException', (err) => {
console.log('error', err);
});
async function loadUser(id) {
try {
return await db.users.find(id);
} catch (e) {
console.log(e);
}
}
async function charge(order) {
try {
await payments.charge(order);
} catch (e) {
throw new Error('Payment failed');
}
}
function readConfig() {
fs.readFile('config.json', (err, data) => {
if (err) throw err;
config = JSON.parse(data);
});
}
Коротко
Что должен найти ревьюер
- Ошибкастрока 1После
uncaughtExceptionпроцесс в неопределённом состоянии; его надо залогировать и завершить (process.exit(1)), чтобы оркестратор перезапустил. Продолжать работу опасно. - Стильстрока 2
console.logвместо структурного логгера с уровнем error: ошибку не найдут по уровню и не построят алерт. - Ошибкастрока 9Ошибка проглатывается, функция возвращает
undefined: вызывающий решит, что пользователя нет (404 вместо 500), сбой БД станет невидимым. - Ошибкастрока 17Исходная причина теряется: нужен
new Error(..., { cause: e }), иначе при разборе инцидента непонятно, отказ банка это, таймаут или баг. - Ошибкастрока 23
throwвнутри колбэка не ловится ни вызывающим кодом, ни try/catch: это uncaughtException. Нужен промис-APIfs.promises.readFileс обработкой. - Ошибкастрока 24
JSON.parseбитого конфига тоже бросит в колбэке; иconfigпишется в неявную глобальную переменную, а читающий код может обратиться к ней до загрузки.
Разбор
Разделяем ошибки на операционные (сеть, таймаут, нет файла: ожидаемы, обрабатываем) и программные (баг: undefined is not a function). Программные не лечатся в рантайме: правильная реакция на uncaughtException и unhandledRejection это лог и выход с ненулевым кодом, рестарт сделает оркестратор.
Антипаттерны в коде: проглатывание (catch с одним console.log), подмена ошибки без cause, throw из колбэка, где его некому поймать. Конфиг читают синхронно на старте (это нормально, сервис ещё не обслуживает запросы) и валидируют схемой: упасть на старте с понятной ошибкой лучше, чем через час на первом обращении.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Структурный лог с маскированием секретов
Следующий вопрос
Что можно делать в process.on("exit")