F-06 real-data verification — partial success (rate-limit ban) + observability gap
Outcome
Partial success: code path verified до WB API, но real data pull blocked sustained rate-limit ban (token quota exhausted после многократных smoke попыток в течение дня).
Что подтверждено working:
init_engine+get_session+ RLSorganization_context— без ошибок открывают session подrazmakh_app._create_run— INSERT intoetl.run(running) выполняется, run_id присваивается (UUID v7).ProxyPool.from_env()— pool initializes 60 proxies (proxy_pool_size=60в logs).- WB statistics-api request формируется корректно (URL, token fingerprint, dateFrom param).
WBClient._handle_429правильно parsesX-Ratelimit-Retry/Retry-Afterheader (видимwait_sec=3988.0для statistics-api,wait_sec=83045.0для common-api в structured logs).- Rate limiter
get_global_limiter().acquire(token, url)per-(token, endpoint) bucket срабатывает без exceptions.
Что не подтверждено реальными данными:
parse_responseна live WB JSON (только smoke с empty payload симулировался ранее).upsertвraw.payloadс реальным sales array.compute_next_cursoradvancingdateFromна основе reallastChangeDate.- End-to-end commit transaction (см. observability gap ниже).
WB endpoint rate-limit reality (verified)
| Endpoint | Rate ban observed |
|---|---|
https://common-api.wildberries.ru/api/v1/seller-info | 23+ часа (83045s) |
https://statistics-api.wildberries.ru/api/v1/supplier/sales | 66 мин (3988s) |
Ключевой вывод: WB rate-limit per-token (НЕ per-IP) — proxy pool не обходит. Когда token
переходит порог 429 → sustained cooldown сильно > 60s. Это исследовано в
research/C-wb-api-inventory.md “Rate limits & задержки данных”, но обнаружено эмпирически
при попытке smoke сегодня. Implication для production: повторные failed runs на одном token
=> spiral lockout. Нужен circuit breaker (после 3 подряд 429 — wait min 1h, не resched).
Observability gap (P20 finding)
etl.run table осталась пустой после нескольких killed runs, хотя в logs видели
etl.run.started с присвоенным run_id.
Причина: run_collector в apps/api/src/razmakh_api/etl/runner.py:193 оборачивает весь
lifecycle в одну transaction (async with get_session() as session, organization_context(...)),
COMMIT происходит только после finalize_run. При SIGKILL (timeout / pkill) — rollback
автоматический, etl.run INSERT откатывается.
Fix: _create_run нужно делать в отдельной transaction (commit сразу), чтобы running runs
были видимы в DB для observability / dashboards. Запиcaть в backlog как F-06.1.
Что осталось deferred
- F-06.1 (new): split
etl.runstart commit в отдельную transaction. P20 issue для GitHub. - F-06.2 (new): circuit breaker для WB token — после N подряд 429 wait min 1h перед следующей попыткой (защита от spiral lockout).
- Block 3 (orders+sales section): parse sales JSON в
core.saletable — покаupsertпишет только вraw.payload. Это by-design для Phase 1 simple version. - Live retry: дождаться ≥1ч после последнего 429 и повторить
sudo bash /tmp/run_sales_full.sh salesна razmakh-vps для full end-to-end verification.
Metrics
- Code path completion: 8/12 checkpoints (init_engine ✓, RLS context ✓, etl.run.start ✓, cursor load ✓, smoke ✓, fetch URL build ✓, rate limit acquire ✓, 429 handler ✓ — но: actual fetch ✗, parse_response ✗, upsert ✗, finalize commit ✗).
- Total time invested today: ~30 min (multiple retry attempts + diagnosis + lesson).
- Files touched: 0 (verification only, no code changes per task spec).
Lesson learned
В контексте verification против rate-limited APIs (WB statistics, advert, finance) — НЕ запускать smoke runs повторно в коротком окне. Один failed run + 429 = ban на 60-1500 мин. Сначала dry-run с локальным mock сервером, потом ровно одна попытка против real API.
Observability invariant: для long-running orchestrators (ETL, jobs, sagas) — entity start должен коммититься в отдельной transaction, иначе killed processes становятся invisible. Это критический gap для on-call (нельзя ответить “что сейчас выполняется?” из DB).
Verification
- Real WB API HTTP requests sent (visible в structlog:
wb.api.getevents with token_fp, url, params). - 429 response parsed correctly (
X-Ratelimit-RetryandRetry-Afterheaders both honored). - DB schema deployed (alembic migration
0002_etl_schema_and_seed.pyapplied — confirmed via\dt etl.*and\dt raw.*showing all 5 expected tables + partitionpayload_y2026m05/06). - Seed данные присутствуют:
organization_id=019e3657-e3ef-7cd0-850e-445d9021c9d4,marketplace_account_id=019e3657-e3f0-7993-a6c0-5dba12f727c7(refs в plan/00 F-06).
Дополнительные ссылки
lessons/f06-skipped-research-halturность-2026-05-17.md— почему research prereqs важно.research/C-wb-api-inventory.md§Rate limits — WB rate limit per-token spec.research/H-wb-api-deep.md§X-Ratelimit-Retry — header handling per spec.
Notes
- Lesson также сохраняется в
netnik-state/lessons/razmakh-f06-real-data-verified-2026-05-17.mdper P16 dual-storage.