fix(openalex): ограничить retry на 429 и добавить экспоненциальный backoff
All checks were successful
Deploy / test (push) Successful in 2m58s
Deploy / deploy (push) Successful in 2s

Было: на 429 плоское ожидание 60с и retry без счётчика — при нескольких
параллельных источниках (4 воркера) каждый продлевал общий rate limit
сам, получался самоподдерживающийся затык без единого успешного запроса
по 20+ минут. Теперь: до 5 попыток с экспоненциальным backoff
(60/120/240/480/960с), после — источник сдаётся с тем, что успел
собрать, вместо вечного retry.
This commit is contained in:
jze9
2026-08-26 16:32:02 +05:00
parent 237e1767a7
commit 344f78b795

View File

@@ -93,6 +93,8 @@ class OpenAlexParser(BaseParser):
cursor = "*"
per_page = min(200, limit)
total_fetched = 0
rate_limit_retries = 0
MAX_RATE_LIMIT_RETRIES = 5
while total_fetched < limit:
params: dict[str, Any] = {
@@ -135,6 +137,7 @@ class OpenAlexParser(BaseParser):
yield works
total_fetched += len(works)
rate_limit_retries = 0 # успешный запрос — сбросить счётчик
# Следующий курсор
cursor = data.get("meta", {}).get("next_cursor")
@@ -147,8 +150,19 @@ class OpenAlexParser(BaseParser):
except httpx.HTTPStatusError as e:
logger.error(f"OpenAlex HTTP ошибка: {e.response.status_code}")
if e.response.status_code == 429:
logger.warning("Rate limit! Ожидаем 60 секунд...")
time.sleep(60)
rate_limit_retries += 1
if rate_limit_retries > MAX_RATE_LIMIT_RETRIES:
logger.error(
f"OpenAlex: {MAX_RATE_LIMIT_RETRIES} подряд 429 — сдаюсь, "
f"забрано {total_fetched}/{limit}"
)
break
# Экспоненциальный backoff: 60/120/240/480/960с — при нескольких
# параллельных воркерах плоское ожидание 60с не давало общему
# лимиту освободиться, каждый воркер продлевал блокировку сам.
wait = 60 * (2 ** (rate_limit_retries - 1))
logger.warning(f"Rate limit! Попытка {rate_limit_retries}/{MAX_RATE_LIMIT_RETRIES}, ждём {wait}с...")
time.sleep(wait)
continue
break
except Exception as e: