stop infinite retry loop on rejected Lichess tokens
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 12s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 12s
A gamer's periodic check would get permanently stuck if their stored token was revoked/expired: our stats API collapsed both "Lichess rejected the token" (401/403, permanent) and genuine transient errors into the same 502 response, so the bot treated an invalid token exactly like a network blip — retrying the same window forever at a capped 300s backoff, never advancing the checkpoint (observed in prod: Dor1zz stuck for 100+ consecutive errors over 8+ hours, admin alerts firing every 25 failures). Preserve the distinction that already existed one layer down (lichess_client.py already tells 401/403 apart from other failures) instead of collapsing it in stats_service.py: add PuzzleOfPeriodResponse.auth_failed, have main.py return 401 specifically for that case, and have the bot raise a distinct InvalidTokenError instead of returning None. On InvalidTokenError, the bot now clears the token for that pair, notifies the user to reconnect via /addtoken, and continues tracking games normally instead of stalling forever.
This commit is contained in:
parent
8080921141
commit
619c00aa06
7 changed files with 70 additions and 16 deletions
|
|
@ -23,7 +23,7 @@ from config import (
|
|||
)
|
||||
from version import BOT_VERSION
|
||||
from database import Database
|
||||
from lichess_api import LichessAPI
|
||||
from lichess_api import LichessAPI, InvalidTokenError
|
||||
from formatters import StatsFormatter
|
||||
from i18n import t
|
||||
from admin_bot import get_admin_bot, init_admin_bot
|
||||
|
|
@ -1713,19 +1713,38 @@ class LichessBot:
|
|||
continue
|
||||
|
||||
if gamer.get('token'):
|
||||
# Ошибки получения пазлов обрабатываются так же, как ошибки игр:
|
||||
# Транзитные ошибки получения пазлов обрабатываются так же, как ошибки игр:
|
||||
# исключение всплывает во внешний обработчик, чекпоинт не продвигается,
|
||||
# то же окно ретраится на следующей итерации (не считаем "пазлов не было").
|
||||
# InvalidTokenError — отдельный случай: Lichess отклонил токен насовсем
|
||||
# (401), ретраить бессмысленно — это раньше приводило к вечному циклу
|
||||
# ретраев без продвижения чекпоинта (см. историю с Dor1zz). Вместо этого
|
||||
# отключаем пазлы для этой пары и продолжаем отслеживать партии как обычно.
|
||||
logger.info(f"📥 Adding puzzles request to queue for {gamer['username']}")
|
||||
puzzles_data = await self.request_queue.add_request(
|
||||
self.lichess_api.get_puzzles_period,
|
||||
gamer['token'], since_timestamp, until_timestamp_approx, 150
|
||||
)
|
||||
if puzzles_data is None:
|
||||
raise RuntimeError("Puzzles period API returned no data")
|
||||
# Обновляем фактическое время после получения ответа по пазлам
|
||||
request_end_time = datetime.now()
|
||||
logger.info(f"✅ Puzzles API response received for {gamer['username']} at {request_end_time}")
|
||||
try:
|
||||
puzzles_data = await self.request_queue.add_request(
|
||||
self.lichess_api.get_puzzles_period,
|
||||
gamer['token'], since_timestamp, until_timestamp_approx, 150
|
||||
)
|
||||
except InvalidTokenError:
|
||||
logger.warning(f"🔑 Token rejected by Lichess for {gamer['username']} (user {user_id}); disabling puzzle tracking for this pair")
|
||||
self.db.clear_user_gamer_token(user_id, gamer['id'])
|
||||
gamer['token'] = None
|
||||
puzzles_data = None
|
||||
try:
|
||||
user_lang = self.db.get_user_language(user_id)
|
||||
await self.application.bot.send_message(
|
||||
chat_id=user_id,
|
||||
text=t('token_rejected_notice', user_lang, username=gamer['username'])
|
||||
)
|
||||
except Exception as notify_err:
|
||||
logger.error(f"Failed to notify user {user_id} about rejected token: {notify_err}")
|
||||
else:
|
||||
if puzzles_data is None:
|
||||
raise RuntimeError("Puzzles period API returned no data")
|
||||
# Обновляем фактическое время после получения ответа по пазлам
|
||||
request_end_time = datetime.now()
|
||||
logger.info(f"✅ Puzzles API response received for {gamer['username']} at {request_end_time}")
|
||||
|
||||
# Сбрасываем счетчик ошибок при успешном запросе
|
||||
consecutive_errors = 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue