diff --git a/app/database/database.py b/app/database/database.py index 4646e282..db591002 100644 --- a/app/database/database.py +++ b/app/database/database.py @@ -1,27 +1,47 @@ import logging from typing import AsyncGenerator - from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker -from sqlalchemy.pool import NullPool - +from sqlalchemy.pool import NullPool, AsyncAdaptedQueuePool from app.config import settings from app.database.models import Base logger = logging.getLogger(__name__) +if settings.get_database_url().startswith("sqlite"): + poolclass = NullPool + pool_kwargs = {} +else: + poolclass = AsyncAdaptedQueuePool + pool_kwargs = { + "pool_size": 20, # Базовый пул (увеличено для высокой нагрузки) + "max_overflow": 30, # Дополнительные соединения при пиках + "pool_timeout": 30, # Таймаут получения соединения + "pool_recycle": 3600, # Обновление соединений каждый час + "pool_pre_ping": True, # Проверка соединения перед использованием + } + engine = create_async_engine( settings.get_database_url(), - poolclass=NullPool, + poolclass=poolclass, echo=settings.DEBUG, - future=True + future=True, + **pool_kwargs, + connect_args={ + "server_settings": { + "application_name": "remnawave_bot", + "jit": "on", + }, + "command_timeout": 60, + "timeout": 10, + } if not settings.get_database_url().startswith("sqlite") else {}, ) AsyncSessionLocal = async_sessionmaker( bind=engine, class_=AsyncSession, expire_on_commit=False, - autoflush=True, - autocommit=False + autoflush=False, + autocommit=False, ) @@ -33,8 +53,6 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]: except Exception: await session.rollback() raise - finally: - await session.close() async def init_db(): diff --git a/app/services/payment/pal24.py b/app/services/payment/pal24.py index 89fd01c8..70973dee 100644 --- a/app/services/payment/pal24.py +++ b/app/services/payment/pal24.py @@ -250,6 +250,10 @@ class Pal24PaymentMixin: return True if status in {"PAID", "SUCCESS", "OVERPAID"}: + metadata = getattr(payment, "metadata_json", {}) or {} + if not isinstance(metadata, dict): + metadata = {} + payment = await payment_module.update_pal24_payment_status( db, payment, @@ -262,7 +266,7 @@ class Pal24PaymentMixin: payment_method=( postback.get("payment_method") or postback.get("PaymentMethod") - or (payment.metadata_json or {}).get("selected_method") + or metadata.get("selected_method") or getattr(payment, "payment_method", None) ), balance_amount=postback.get("BalanceAmount") @@ -281,6 +285,10 @@ class Pal24PaymentMixin: trigger="postback", ) + metadata = getattr(payment, "metadata_json", {}) or {} + if not isinstance(metadata, dict): + metadata = {} + await payment_module.update_pal24_payment_status( db, payment, @@ -709,8 +717,9 @@ class Pal24PaymentMixin: "secondary_url": secondary_url, "sbp_url": links_map.get("sbp"), "card_url": links_map.get("card"), - "link_page_url": links_map.get("page") or payment.link_page_url, - "link_url": payment.link_url, + "link_page_url": links_map.get("page") + or getattr(payment, "link_page_url", None), + "link_url": getattr(payment, "link_url", None), "selected_method": selected_method, } @@ -878,7 +887,10 @@ class Pal24PaymentMixin: ) -> tuple[Dict[str, str], str]: links: Dict[str, str] = {} - metadata = payment.metadata_json if isinstance(payment.metadata_json, dict) else {} + metadata = getattr(payment, "metadata_json", {}) or {} + if not isinstance(metadata, dict): + metadata = {} + if metadata: links_meta = metadata.get("links") if isinstance(links_meta, dict):