feat(nalogo): система очереди чеков с отложенной отправкой

Реализована отказоустойчивая система отправки чеков в налоговую:

  - Добавлен NalogoQueueService для фоновой обработки очереди чеков
  - При недоступности nalog.ru (503) чеки сохраняются в Redis
  - Автоматическая повторная отправка с настраиваемым интервалом
  - Защита от DDoS: задержка между чеками (NALOGO_QUEUE_RECEIPT_DELAY)
  - Уведомления админам в топик при проблемах и успешной разгрузке

  Изменения в файлах:
  - app/services/nalogo_queue_service.py: новый фоновый сервис
  - app/services/nalogo_service.py: методы очереди, определение 503
  - app/utils/cache.py: lpush/rpop/llen/lrange для Redis List
  - app/handlers/admin/monitoring.py: статистика чеков в админке
  - app/config.py: NALOGO_QUEUE_* и ADMIN_NOTIFICATIONS_NALOG_TOPIC_ID
  - main.py: интеграция запуска/остановки сервиса

  Новые ENV переменные:
  - ADMIN_NOTIFICATIONS_NALOG_TOPIC_ID
  - NALOGO_QUEUE_CHECK_INTERVAL (300с)
  - NALOGO_QUEUE_RECEIPT_DELAY (3с)
  - NALOGO_QUEUE_MAX_ATTEMPTS (10)
This commit is contained in:
gy9vin
2025-12-25 23:01:49 +03:00
parent da46e39c61
commit 0df3018703
8 changed files with 606 additions and 11 deletions
+33
View File
@@ -34,6 +34,7 @@ from app.services.external_admin_service import ensure_external_admin_token
from app.services.broadcast_service import broadcast_service
from app.services.referral_contest_service import referral_contest_service
from app.services.contest_rotation_service import contest_rotation_service
from app.services.nalogo_queue_service import nalogo_queue_service
from app.utils.startup_timeline import StartupTimeline
from app.utils.timezone import TimezoneAwareFormatter
@@ -271,6 +272,11 @@ async def main():
payment_service = PaymentService(bot)
auto_payment_verification_service.set_payment_service(payment_service)
# Настройка сервиса очереди чеков NaloGO
if payment_service.nalogo_service:
nalogo_queue_service.set_nalogo_service(payment_service.nalogo_service)
nalogo_queue_service.set_bot(bot)
verification_providers: list[str] = []
auto_verification_active = False
async with timeline.stage(
@@ -331,6 +337,27 @@ async def main():
if auto_verification_active:
stage.log("Фоновая автопроверка запущена")
async with timeline.stage(
"Очередь чеков NaloGO",
"🧾",
success_message="Сервис очереди чеков запущен",
) as stage:
if settings.is_nalogo_enabled():
try:
await nalogo_queue_service.start()
if nalogo_queue_service.is_running():
queue_len = await payment_service.nalogo_service.get_queue_length()
if queue_len > 0:
stage.log(f"В очереди ожидает {queue_len} чек(ов)")
stage.success("Фоновая обработка чеков активна")
else:
stage.skip("Сервис не запущен")
except Exception as e:
stage.warning(f"Ошибка запуска очереди чеков: {e}")
logger.error(f"❌ Ошибка запуска очереди чеков NaloGO: {e}")
else:
stage.skip("NaloGO отключен настройками")
async with timeline.stage(
"Внешняя админка",
"🛡️",
@@ -646,6 +673,12 @@ async def main():
except Exception as e:
logger.error(f"Ошибка остановки ротации игр: {e}")
logger.info("ℹ️ Остановка очереди чеков NaloGO...")
try:
await nalogo_queue_service.stop()
except Exception as e:
logger.error(f"Ошибка остановки очереди чеков NaloGO: {e}")
logger.info("ℹ️ Остановка сервиса бекапов...")
try:
await backup_service.stop_auto_backup()