Порядок выполнения запроса
Уровни выполнения
Клиент различает:
- операцию — один логический HTTP-запрос с постоянным
operationId; - попытку — одно обращение к транспорту, включая повтор после
5xx,429или успешного обновления авторизации.
OperationTransformer вызывается один раз и работает с результатом публичного метода. AttemptInterceptor вызывается для каждой сетевой попытки и получает сырой Response.
Порядок выполнения
плагины операции
→ контракт операции (read)
→ выбор сервиса
→ предварительная подготовка авторизации
→ повторные попытки
→ обновление авторизации после 401
→ подготовка авторизации к попытке
→ очередь конечного URL.origin
→ номер попытки
→ актуальные заголовки авторизации
→ перехватчики попытки и транспортПри возврате результата транспорт снимает HTTP-обёртку, стадия контракта преобразует тело в предметную модель, затем значение возвращается плагинам операции. Ответ, который плагин вернул без next(), считается готовым.
deadline ограничивает операцию — всю цепочку от плагинов до транспорта, timeout — одну попытку. signal вызывающего кода обрывает и операцию, и попытку.
При отключённом ограничителе стадия очереди отсутствует. Номер присваивается после ожидания очереди и считает фактические обращения к транспорту. После 401 исходная операция получает следующий номер попытки, а auth.refresh выполняется как отдельная операция:
users.me: attempt 1 → 401
auth.refresh: attempt 1 → 200
users.me: attempt 2 → 200Инварианты
- Локальный результат
OperationTransformerне входит в очередь и не расходует лимит. - Пауза между повторами не занимает место в очереди; новая попытка планируется заново.
- Число повторов после
429ограничено длинойretryDelays, в том числе при заголовкеRetry-After.timeoutпаузы между повторами не ограничивает. - Истёкший
timeoutповторяется как сетевой сбой: только для safe- и idempotent-операций. Истёкшийdeadlineи отмена не повторяются,onRetryне вызывается. onErrorполучает каждую ошибку не более одного раза: ошибку попытки, ошибку стадии до транспорта, отмену или истёкшийdeadline. Ошибка истёкшего срока в хуке и у вызывающего кода — один объектItdTimeoutError.- Сервис и разовый
baseUrlразрешаются до выбора очереди. Ключом служит пара «итоговыйURL.origin— серверный бакет». Разные имена одного адреса делят ограничитель, а операции из разных бакетов не мешают друг другу. Ключ не меняется между попытками. - Очередь двухуровневая: задача занимает слот своего бакета, затем общий слот направления. Пауза бакета удерживает её до захвата общего слота, поэтому притормозивший счётчик не занимает общую ёмкость, а суммарная одновременность остаётся равна
concurrency. - Подготовка авторизации не занимает место в очереди. Отложенный вход и предварительное обновление выполняются до retry исходного запроса, но сами проходят тот же pipeline как отдельные операции со своими
operationIdиRetrySafety. - Заголовки авторизации читаются после ожидания очереди, перед транспортом.
- После
401авторизация обновляется не более одного раза. operationId, HTTP-метод иRetrySafetyвстроенных операций берутся из единого каталога.- Составной метод может выполнить несколько операций; каждая проходит плагины отдельно.
- После начала
dispose()новые пользовательские операции запрещены. Только внутренние запросы отправки накопленной телеметрии могут завершиться.
Выбор точки расширения
Используйте operations.use() для кэширования, шифрования, подмены или преобразования результата. Используйте attempts.use(), если нужны итоговый URL, заголовки, подпись запроса, сетевые метрики или сырой Response каждой попытки.
Подробные типы и примеры находятся в руководстве по плагинам.