From 8246e9a5905292a77726d9a591566478bbd66936 Mon Sep 17 00:00:00 2001 From: Machka Pasla <161734431+machka-pasla@users.noreply.github.com> Date: Tue, 29 Jul 2025 14:44:55 +0300 Subject: [PATCH] Close sessions for all services on shutdown --- bot/main_bot.py | 38 ++++++++++++++++++++++++++---- bot/services/crypto_pay_service.py | 9 +++++++ bot/services/panel_api_service.py | 4 ++++ bot/services/yookassa_service.py | 4 ++-- 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/bot/main_bot.py b/bot/main_bot.py index b843387..251cf93 100644 --- a/bot/main_bot.py +++ b/bot/main_bot.py @@ -193,11 +193,38 @@ async def on_startup_configured(dispatcher: Dispatcher): async def on_shutdown_configured(dispatcher: Dispatcher): logging.warning("SHUTDOWN: on_shutdown_configured executing...") + async def close_service(key: str) -> None: + service = dispatcher.get(key) + if not service: + return + close_coro = getattr(service, "close", None) + if callable(close_coro): + try: + await close_coro() + logging.info(f"{key} closed on shutdown.") + except Exception as e: + logging.warning(f"Failed to close {key}: {e}") + else: + close_session = getattr(service, "close_session", None) + if callable(close_session): + try: + await close_session() + logging.info(f"{key} session closed on shutdown.") + except Exception as e: + logging.warning(f"Failed to close session for {key}: {e}") - panel_service: Optional[PanelApiService] = dispatcher.get("panel_service") - if panel_service and hasattr(panel_service, "close_session"): - await panel_service.close_session() - logging.info("Panel API service session closed on shutdown.") + for service_key in ( + "panel_service", + "cryptopay_service", + "tribute_service", + "panel_webhook_service", + "yookassa_service", + "promo_code_service", + "stars_service", + "subscription_service", + "referral_service", + ): + await close_service(service_key) bot: Bot = dispatcher["bot_instance"] if bot and bot.session: @@ -314,7 +341,8 @@ async def run_bot(settings_param: Settings): dp.update.outer_middleware(ActionLoggerMiddleware(settings=settings_param)) dp.startup.register(on_startup_configured) - dp.shutdown.register(lambda: on_shutdown_configured(dp)) + # Register shutdown callback directly so Dispatcher instance is provided + dp.shutdown.register(on_shutdown_configured) await register_all_routers(dp, settings_param) diff --git a/bot/services/crypto_pay_service.py b/bot/services/crypto_pay_service.py index 05bc388..b2a40a9 100644 --- a/bot/services/crypto_pay_service.py +++ b/bot/services/crypto_pay_service.py @@ -46,6 +46,15 @@ class CryptoPayService: self.client = None self.configured = False + async def close(self): + """Close underlying AioCryptoPay session if initialized.""" + if self.client: + try: + await self.client.close() + logging.info("CryptoPay client session closed.") + except Exception as e: + logging.warning(f"Failed to close CryptoPay client: {e}") + async def create_invoice( self, session: AsyncSession, diff --git a/bot/services/panel_api_service.py b/bot/services/panel_api_service.py index e5639ae..b76cad0 100644 --- a/bot/services/panel_api_service.py +++ b/bot/services/panel_api_service.py @@ -34,6 +34,10 @@ class PanelApiService: self._session = None logging.info("Panel API service HTTP session closed.") + async def close(self): + """Alias for close_session for API consistency.""" + await self.close_session() + async def _prepare_headers(self) -> Dict[str, str]: headers = { "Content-Type": "application/json", diff --git a/bot/services/yookassa_service.py b/bot/services/yookassa_service.py index 4bb96e6..43aaeae 100644 --- a/bot/services/yookassa_service.py +++ b/bot/services/yookassa_service.py @@ -142,7 +142,7 @@ class YooKassaService: f"Amount: {amount} {currency}. Metadata: {metadata}. Receipt: {receipt_data_dict}" ) - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() response = await loop.run_in_executor( None, lambda: YooKassaPayment.create(payment_request, idempotence_key)) @@ -196,7 +196,7 @@ class YooKassaService: f"Fetching payment info from YooKassa for ID: {payment_id_in_yookassa}" ) - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() payment_info_yk = await loop.run_in_executor( None, lambda: YooKassaPayment.find_one(payment_id_in_yookassa))