РуководстваОпубликовано: 09.11.2026• 0 просмотров

API вернул 202 без результата: состояния асинхронных заданий, опрос и повторная отправка

Различайте приём задания, успешную проверку статуса и завершение работы. Сохраняйте ID, ограничивайте опрос и разбирайте 404, истечение срока результата и неизвестный исход отправки без повторного создания задания.

API вернул HTTP 202, но в теле есть только идентификатор задания, без результата генерации. Затем запросы статуса получают 200, а интерфейс продолжает показывать ожидание. Не отправляйте исходное задание повторно: успешная отправка, успешное чтение статуса и успешное выполнение — три разных факта.

Статья относится к API с явно описанным протоколом асинхронных заданий, например для обработки документов или пакетных операций. Она не предполагает, что такой режим поддерживает любая модель или сервис-посредник. Источники проверены 2026-11-09; код проверялся только на искусственных локальных данных, без реальных платформ и платных API.

1. Ответ 202 не является результатом и не превратится в 200 на том же соединении

В разделе 15.3.3 RFC 9110 сказано: 202 означает, что запрос принят для обработки, но обработка ещё не завершена. В итоге операция может даже не состояться.[1] После завершения первоначального HTTP-ответа сервер не отправит автоматически новый «окончательный код статуса» в рамках этого ответа. Клиент должен по протоколу API запросить состояние, получить результат или дождаться настроенного уведомления.

Найдите в официальной документации четыре вещи: адрес и метод отправки, идентификатор задания, адрес проверки состояния, конечные состояния и способ получения результата. В архитектурном шаблоне Microsoft Location указывает на ресурс статуса, а Retry-After помогает выбрать интервал проверки. Это шаблон проектирования, а не требование наличия обоих заголовков в любом ответе 202.[2]

Что полученоЧто можно подтвердитьЧто пока не подтверждено
Ответ 202 на отправку и ID заданияИнтерфейс сообщает, что запрос принятРабота уже началась, обязательно завершится успешно или будет бесплатной
Ответ 200 на проверку статусаЭта проверка успешно вернула представление ресурсаСамо задание завершено
Успешное конечное состояниеСервер сообщает о завершении заданияСсылка на скачивание ещё действует и результат отвечает требованиям
Исчерпан бюджет ожидания клиентаТекущий сеанс наблюдения закончилсяУдалённое задание завершилось ошибкой или отменено

Если документация описывает только синхронный ответ и не определяет ресурс задания, не придумывайте пути /jobs или /status. Идентификатор HTTP-запроса тоже не обязательно является ID задания, доступным для поиска: сначала установите назначение каждого номера.

2. Сохраните идентичность одной отправки и проверяйте то же задание

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

Например, учебный протокол может вернуть job_demo, а затем последовательность queued, running, succeeded. queued и running — промежуточные состояния. failed и canceled тоже конечные, но не успешные. Названия полей и регистр определяет конкретный протокол; у него могут быть состояния истечения срока или частичного успеха. Не трактуйте любое незнакомое значение как «продолжать ждать».

До проверки статуса проверьте и адрес:

  • Используйте адрес из проверенного протокола; уточните HTTPS, хост, порт, путь и область действия учётных данных.
  • Location может указывать на другой хост. Обращайтесь к нему только в рамках заранее разрешённого протокола; не пересылайте исходный API Key на произвольный адрес или на каждую цель перенаправления.
  • Ссылка на результат с параметрами подписи может сама давать доступ к данным. Ей не место в открытых логах, обращениях в поддержку и скриншотах браузера.
  • Адрес статуса и адрес скачивания могут различаться. Следуйте процедуре получения результата; перенаправление на скачивание не является командой повторить исходный POST.

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

3. Локальный пример: сначала идентификатор и состояние, затем результат

Ниже интерпретатор снимка состояния для собственного учебного протокола: id должен совпадать, status принимает только пять перечисленных значений, а при успехе result.text должен быть строкой, включая пустую. Пустая строка здесь допустима по формату; её пригодность для бизнеса проверяется отдельно. Адаптер реального сервиса должен преобразовывать поля и конечные состояния по его официальным правилам, а не предполагать совместимость.

class JobProtocolError(ValueError):
    pass


def interpret_status(snapshot, expected_id):
    if not isinstance(expected_id, str) or not expected_id.strip():
        raise ValueError("expected_id must be a non-empty string")
    if not isinstance(snapshot, dict):
        raise JobProtocolError("NOT_AN_OBJECT")
    if snapshot.get("id") != expected_id:
        raise JobProtocolError("JOB_ID_MISMATCH")
    state = snapshot.get("status")
    if not isinstance(state, str):
        raise JobProtocolError("INVALID_STATUS")
    if state in ("queued", "running"):
        return "wait", None
    if state in ("failed", "canceled"):
        return "stop", state
    if state == "succeeded":
        result = snapshot.get("result")
        if not isinstance(result, dict) or not isinstance(result.get("text"), str):
            raise JobProtocolError("INVALID_RESULT")
        return "done", result["text"]
    raise JobProtocolError("UNKNOWN_STATUS")

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

wait означает только, что этот снимок ещё не завершён; это не разрешение опрашивать сервер бесконечно. stop обозначает конечную ошибку или отмену: сохраните состояние и обезличенную диагностическую информацию и закончите наблюдение. Нельзя незаметно заменить неуспешное задание новой отправкой. done возвращается лишь при совпадении ID, успешном состоянии и корректной структуре результата примера.

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

4. Установите три отдельных бюджета проверки

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

Для измерения прошедшего времени внутри процесса подходит time.monotonic(): по документации Python эти часы не зависят от изменения системного времени. Их точка отсчёта не имеет бизнес-смысла, использовать следует разность показаний.[3] Для восстановления в другом процессе сохраняйте бизнес-дедлайн с часовым поясом и пересчитывайте бюджет; не считайте старое значение таймера переносимой временной меткой.

Если протокол предусматривает Retry-After, планируйте следующую проверку согласно его значению. Заголовок может содержать неотрицательное целое число секунд или HTTP-дату. Он не обещает, что задание обязательно завершится к этому времени.[1] При некорректном значении применяйте явно заданную политику клиента, а не немедленный цикл без пауз. Если заголовка нет, используйте рекомендованный протоколом интервал, ограниченное увеличение задержки и случайный разброс; не проверяйте множество заданий каждую миллисекунду.

Допустим, у клиента осталось 20 секунд на наблюдение, а сервер требует ждать не менее 60 секунд до следующей проверки. Сохраните ID и состояние «проверить позже», затем завершите текущий сеанс. Нельзя сокращать ожидание до 20 секунд и обращаться раньше. Числа здесь иллюстративные, не рекомендуемая конфигурация. При возобновлении проверяйте прежнее задание, не создавайте новое.

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

5. Обрабатывайте сбой на его этапе и не записывайте неизвестность как ошибку задания

НаблюдениеРекомендуемое действиеЧего избегать
Соединение оборвалось при отправке, ID не полученСохранить номер попытки; проверить приём через документированный поиск, механизм идемпотентности или поддержкуРешить, что без ID задание точно не создано, и сразу повторить
Проверка возвращает 401 или 403Уточнить аккаунт, проект, окружение и права на ресурс статусаСменить аккаунт и угадывать результат по старому ID
Проверка возвращает 404Проверить адрес, ID, видимость и срок хранения; ждать появления ресурса лишь когда это допускает протоколВсегда считать 404 очередью или доказательством отсутствия приёма
Проверка возвращает 429 или временный 5xxПовторять проверку в пределах бюджета, сохраняя исходное заданиеПревращать повтор проверки в новую отправку
Состояние долго не меняетсяСопоставить время отправки, обновления статуса, объявления сервиса и оговорённый срокЖдать бесконечно после одного running
После успеха ссылка на результат перестала работатьВыяснить, можно ли получить новый адрес для того же задания; проверить срок храненияИз-за ошибки скачивания повторно запускать всю платную работу

Microsoft отмечает, что некоторые реализации возвращают 404 до создания ресурса результата, а отдельный ресурс статуса устраняет эту неоднозначность.[2] Это не основание повторять любой 404. Отсутствие записи на платформе тоже не доказывает отсутствие задания: логи и индексы могут обновляться с задержкой.

Применяйте идемпотентную отправку только при явной поддержке сервиса и с соблюдением области ключа, срока действия и требований к одинаковому содержимому для одного ключа. Добавленный клиентом заголовок Idempotency-Key сам по себе не обеспечивает дедупликацию. Если судьба первой отправки неизвестна, сохраните «результат отправки не подтверждён», а не меняйте его на определённую ошибку ради повторного запуска.

Асинхронный интерфейс может также присылать Webhook. Уведомление и опрос способны сообщить об одном завершении, поэтому запись бизнес-результата всё равно требует дедупликации. Проверка подписи уведомлений здесь не реализована; она разобрана в руководстве по Webhook и повторной обработке. Статус задания не равен статусу счёта; для расходов используйте сверку запросов и начислений.

6. Перед запуском проверьте восстановление на искусственных заданиях

На Python 3.12.10 выполнена 21 локальная проверка: очередь без результата, частичный результат во время выполнения, успешный китайский и русский текст и пустая строка, конечная ошибка и отмена, другой ID задания, некорректный снимок и статус, неизвестное состояние, отсутствие или неверный тип результата при заявленном успехе, а также ограниченные последовательности состояний.

Последовательность queued → running → succeeded должна отдавать результат лишь в конечном состоянии. Если лимит проверок исчерпан при running, следует сохранить pending, а не failed. После failed наблюдение не продолжается автоматически, даже если в тестовой очереди есть следующий успешный снимок. Проверялись интерпретатор и локальный тестовый драйвер, а не сетевая реализация опроса.

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

Для поддержки подготовьте время отправки с часовым поясом, обезличенные ID задания и запроса, коды каждой проверки, последнее состояние и сведения об автоматической повторной отправке. Не прикладывайте секреты или полные подписанные URL; используйте шаблон минимального воспроизведения и обезличенного обращения.

7. Первичные источники

  • [1] RFC 9110: HTTP Semantics: семантика 202 Accepted в разделе 15.3.3 и формат Retry-After в разделе 10.2.3.
  • [2] Microsoft Azure Architecture: Asynchronous Request-Reply: шаблон ресурса статуса, опроса, конечных состояний, хранения результатов и дедупликации отправки. Он не подтверждает наличие всех возможностей у сторонней платформы.
  • [3] Python 3.12: time.monotonic: измерение прошедшего времени и ограничения точки отсчёта.

Источники проверены 2026-11-09. Примерные поля состояния и бюджеты не являются обещаниями продукта; при подключении следуйте актуальному протоколу нужного API.

Опубликовано: 9 ноября 2026 г.
最后更新: 09.11.2026

Похожие статьи

Руководства

Длинный ID из API изменился во фронтенде? Точность JavaScript и передача строк

Изменились последние цифры ID, поиск вернул 404 или номера в счёте слились? Проверьте текст JSON, разбор, хранение и повторную отправку; узнайте, почему String и BigInt иногда уже не помогут, и проверьте передачу строковых ID на локальных примерах.

Руководства

Как считать стабильность API: исходные запросы, повторы и конечная успешность

Успех после повтора нельзя считать новым независимым успехом. Статья разделяет request_id, попытки и конечные состояния, объясняет границы 429, 503, тайм-аутов и идемпотентности, а локальный скрипт считает конечную успешность и усиление повторами.

Руководства

Webhook: ошибка подписи или повторная обработка — проверяем исходное тело, время и идемпотентность

Разберите ошибки API-callback по четырём слоям: исходное тело, склейка HMAC, допуск времени и защита от повторов. Локальный пример показывает, почему 2xx и успешная подпись ещё не гарантируют однократный бизнес-эффект.

Отказ от ответственности

Данные о сервисах и ценах вводятся вручную; доступность сайтов проверяется автоматически с указанием времени последней проверки.Информация о провайдерах может меняться, поэтому перед оплатой рекомендуем посетить официальный сайт сервиса. Мы не гарантируем качество услуг сторонних провайдеров.

© 2026 Выбор API. All rights reserved.