АналитикаСистемный анализСистемный аналитик интеграционных систем

Клиент API получает одинаковый ответ для постоянной ошибки валидации и временного сбоя зависимости. Какой п...

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

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Контракт API должен явно различать исправимые клиентом ошибки и временные сбои инфраструктуры. Для этого используют подходящий HTTP-статус вместе со стабильным машинным кодом ошибки: клиентская ошибка должна приводить к исправлению запроса, а временная — допускать ограниченную повторную попытку.

Одного текста сообщения недостаточно: он предназначен для человека и не должен определять алгоритм клиента.

Исторический контекст

В распределённых системах ошибки часто возникали на сетевых границах: зависимость могла быть недоступна, отвечать слишком долго или временно перегружаться. Ранние интеграции нередко возвращали один общий ответ вроде «операция не выполнена», из-за чего клиенты не могли понять, нужно ли менять запрос или повторять его.

Такое различие стало частью практики проектирования HTTP-контрактов. Статус ответа даёт общий класс проблемы, а машинный код и дополнительные поля уточняют причину и ожидаемое действие клиента.

Постановка проблемы

Ошибка валидации постоянна, пока клиент не изменит данные. Повторная отправка такого запроса бесполезна и может создавать лишнюю нагрузку.

Сбой зависимости, напротив, может исчезнуть через несколько секунд. Если клиент воспримет его как окончательную ошибку, пользовательская операция будет потеряна; если начнёт безусловно повторять ошибочный запрос, возникнут лишняя нагрузка, лавина повторов и риск повторного выполнения операции.

Подробное решение

Сначала ошибку классифицируют по ожидаемому действию клиента:

  • Ошибка валидации означает, что запрос нужно изменить. Для неё выбирают клиентский класс HTTP-статуса и стабильный код, например validation_error или более конкретный код поля.
  • Временная недоступность зависимости означает, что запрос может быть повторён позже. Для неё используют серверный класс статуса и код вроде dependency_unavailable.
  • Ограничение частоты выделяют отдельно: клиенту может быть разрешено повторить запрос после указанной задержки, если контракт это сообщает.

В теле ошибки полезно передавать машинный код, понятное сообщение, сведения о проблемных полях и идентификатор корреляции. Машинный код должен быть стабильным: изменение текста сообщения не должно ломать обработку клиента.

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

Разделение ошибок не означает, что каждый временный сбой можно повторять. Например, тайм-аут после отправки запроса не всегда означает, что сервер его не обработал. Поэтому контракт должен учитывать не только техническую причину, но и состояние операции для клиента.

Ситуация из практики

Платёжный сервис получает запрос на создание платежа. В одном случае сумма отрицательна, в другом платёжный шлюз временно недоступен. Изначально оба случая возвращали один ответ с признаком неуспеха.

Рассматривались два варианта. Возвращать только текстовую причину было просто, но ненадёжно: формулировки могли измениться, а локализация ломала бы разбор. Возвращать только разные HTTP-статусы лучше разделяло случаи, но не давало достаточно устойчивой детализации для автоматической обработки.

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

Что кандидаты часто упускают

  1. Достаточно ли разных HTTP-статусов без машинных кодов?

Нет. Статус полезен как общий сигнал, но часто описывает только класс проблемы. Один и тот же класс может включать разные причины и разные действия клиента: например, исправление конкретного поля, повтор после задержки или обращение в поддержку. Поэтому стабильный машинный код нужен для программной логики, а HTTP-статус — для совместимого общего поведения.

  1. Должен ли клиент повторять любой ответ серверного класса?

Нет. Серверский статус указывает, что проблема находится не только в синтаксисе запроса, но не гарантирует временный характер сбоя. Повтор допустим лишь при наличии признаков временности, ограниченной политике попыток и понимании последствий повторного выполнения. Для неизвестного результата особенно важно проверить состояние операции, а не слепо создавать её заново.

  1. Можно ли считать ошибку зависимости временной только потому, что она возникла по сети?

Нет. Сетевой сбой может скрывать уже выполненную операцию, а ответ зависимости может содержать окончательный бизнес-отказ. Нужно различать как минимум постоянный отказ по бизнес-правилам, временную недоступность и неопределённый результат. Для последнего контракт должен предусматривать запрос состояния, ключ операции или другой способ безопасно установить итог, иначе автоматический повтор может привести к дублированию действия.