From 9cb559ff3994c0f1c6ba48a4ec09dec9b391e48b Mon Sep 17 00:00:00 2001 From: c0mrade Date: Fri, 10 Apr 2026 11:04:02 +0300 Subject: [PATCH] fix: enqueue retry on RemnaWave API failure in all purchase flows (BUG-2, BUG-10) Add remnawave_retry_queue.enqueue() calls in all 10 purchase error handlers where RemnaWave API failure was caught and swallowed without scheduling a retry: - cabinet purchase.py: purchase_tariff() and activate_trial() (2 places) - subscription_purchase_service.py: miniapp purchase flow (1 place) - tariff_purchase.py: custom, standard, daily, renewal, switch, daily-switch, and instant-switch flows (7 places) --- .../routes/subscription_modules/purchase.py | 12 ++++++ app/handlers/subscription/tariff_purchase.py | 42 +++++++++++++++++++ app/services/subscription_purchase_service.py | 6 +++ 3 files changed, 60 insertions(+) diff --git a/app/cabinet/routes/subscription_modules/purchase.py b/app/cabinet/routes/subscription_modules/purchase.py index c36cf43c..596666bb 100644 --- a/app/cabinet/routes/subscription_modules/purchase.py +++ b/app/cabinet/routes/subscription_modules/purchase.py @@ -911,6 +911,12 @@ async def purchase_tariff( ) except Exception as remnawave_error: logger.error('Failed to sync subscription with RemnaWave', remnawave_error=remnawave_error) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=user.id, + action='create' if not subscription.remnawave_uuid else 'update', + ) # Save cart for auto-renewal (not for daily tariffs - they have their own charging) if not is_daily_tariff: @@ -1249,6 +1255,12 @@ async def activate_trial( await db.refresh(subscription) except Exception as e: logger.error('Failed to create RemnaWave user for trial', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=user.id, + action='create', + ) # Send admin notification about trial activation try: diff --git a/app/handlers/subscription/tariff_purchase.py b/app/handlers/subscription/tariff_purchase.py index 12442825..b8f9ae21 100644 --- a/app/handlers/subscription/tariff_purchase.py +++ b/app/handlers/subscription/tariff_purchase.py @@ -1078,6 +1078,12 @@ async def handle_custom_confirm( ) except Exception as e: logger.error('Ошибка обновления Remnawave', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Создаем транзакцию await create_transaction( @@ -1602,6 +1608,12 @@ async def confirm_tariff_purchase( ) except Exception as e: logger.error('Ошибка обновления Remnawave', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Создаем транзакцию try: @@ -1875,6 +1887,12 @@ async def confirm_daily_tariff_purchase( ) except Exception as e: logger.error('Ошибка обновления Remnawave', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Создаем транзакцию await create_transaction( @@ -2340,6 +2358,12 @@ async def confirm_tariff_extend( ) except Exception as e: logger.error('Ошибка обновления Remnawave', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Создаем транзакцию await create_transaction( @@ -2966,6 +2990,12 @@ async def confirm_tariff_switch( ) except Exception as e: logger.error('Ошибка обновления Remnawave при переключении тарифа', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Гарантированный сброс устройств при смене тарифа await db.refresh(db_user) @@ -3207,6 +3237,12 @@ async def confirm_daily_tariff_switch( ) except Exception as e: logger.error('Ошибка обновления Remnawave', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Гарантированный сброс устройств при смене тарифа await db.refresh(db_user) @@ -3894,6 +3930,12 @@ async def confirm_instant_switch( ) except Exception as e: logger.error('Ошибка обновления Remnawave при мгновенном переключении', error=e) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=db_user.id, + action='create', + ) # Гарантированный сброс устройств при смене тарифа await db.refresh(db_user) diff --git a/app/services/subscription_purchase_service.py b/app/services/subscription_purchase_service.py index 6b5b70d0..0aba98a5 100644 --- a/app/services/subscription_purchase_service.py +++ b/app/services/subscription_purchase_service.py @@ -1188,6 +1188,12 @@ class MiniAppSubscriptionPurchaseService: ) except Exception as remnawave_error: # pragma: no cover - defensive logging logger.error('Failed to sync subscription with RemnaWave', remnawave_error=remnawave_error) + from app.services.remnawave_retry_queue import remnawave_retry_queue + remnawave_retry_queue.enqueue( + subscription_id=subscription.id, + user_id=user.id, + action='create' if not getattr(subscription, 'remnawave_uuid', None) else 'update', + ) transaction = await create_transaction( db=db,