Release Please / Release Please (push) Skipped
Release / GoReleaser (push) Skipped
Tests / Secret scan (gitleaks) (push) Skipped
Tests / Test (Go 1.25) (push) Skipped
Tests / Test (Go stable) (push) Skipped
Tests / Secret scan (gitleaks) (pull_request) Successful in 5s
Tests / Test (Go 1.25) (pull_request) Successful in 25s
Tests / Test (Go stable) (pull_request) Successful in 27s
56 lines
2.5 KiB
Markdown
56 lines
2.5 KiB
Markdown
---
|
||
type: reference
|
||
status: current
|
||
related:
|
||
- README.md
|
||
- ../AGENTS.md
|
||
---
|
||
|
||
# Rate limit, backoff и cooldown
|
||
|
||
Устойчивость к 429 (openresty). Всё встроено в библиотеку — отдельный пакет не
|
||
нужен. Реализация: `ratelimit.go`, `retry.go`.
|
||
|
||
## Что происходит с каждым запросом
|
||
|
||
1. **Cooldown-гейт** — общий на процесс. Если недавно пришёл 429, все запросы
|
||
ждут конца окна.
|
||
2. **Rate limiter** — token bucket на процесс. Пейсит все HTTP-пути: листинг,
|
||
создание папок, загрузку, `get project`, auth.
|
||
3. Запрос уходит.
|
||
4. Ответ ≥400 → `*TransientError` (для 429/502/503/504) с `Retry-After`.
|
||
5. `DoRetry` — экспоненциальный backoff, без jitter.
|
||
6. `Retry-After` длиннее backoff → ждём его; окно уходит в общий cooldown.
|
||
|
||
Установлено в `NewClient` через `pacedTransport`; отдельный код трогать не надо.
|
||
|
||
## Env
|
||
|
||
| Переменная | Default | Смысл |
|
||
|---|---|---|
|
||
| `OO_RATE_LIMIT` | `4` | запросов/с на процесс; `0` — лимитер выключен |
|
||
| `OO_BURST` | `1` | запас токенов token bucket |
|
||
| `OO_RETRY_ATTEMPTS` | `7` | всего попыток, включая первую |
|
||
| `OO_RETRY_BASE` | `2s` | база экспоненты: ждать перед попыткой N = `Base*2^(N-1)` |
|
||
| `OO_RETRY_MAX` | `2m` | потолок ожидания |
|
||
|
||
Битые значения → default. `OO_RETRY_*` — формат `time.ParseDuration`
|
||
(`2s`, `30s`, `2m`).
|
||
|
||
## Правила
|
||
|
||
- Детерминированно, без jitter — повторный прогон ждёт столько же.
|
||
- `Retry-After` — секунды (`120`) или HTTP-date.
|
||
- Cooldown общий: параллельные и последовательные вызовы не бьют в стену.
|
||
- Backoff cap не ограничивает `Retry-After` — серверу верим больше.
|
||
- Только stdlib.
|
||
|
||
## Когда руками снять нагрузку
|
||
|
||
`OO_RATE_LIMIT` ниже (`2`), `OO_BURST=1`; при массовом apply — батчами.
|
||
|
||
## Тесты
|
||
|
||
`retry_test.go` — `Retry-After`, экспонента, cap; `ratelimit_test.go` — burst,
|
||
`OO_RATE_LIMIT=0`, cooldown. Фейковый сервер отдаёт 429 с заголовком.
|