fix(openalex): ограничить retry на 429 и добавить экспоненциальный backoff
Было: на 429 плоское ожидание 60с и retry без счётчика — при нескольких параллельных источниках (4 воркера) каждый продлевал общий rate limit сам, получался самоподдерживающийся затык без единого успешного запроса по 20+ минут. Теперь: до 5 попыток с экспоненциальным backoff (60/120/240/480/960с), после — источник сдаётся с тем, что успел собрать, вместо вечного retry.
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user