From 9708a56fd738754e2327a93538e9ef91d8665b3d Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 9 Nov 2025 08:14:41 +0300 Subject: [PATCH 1/4] Update database.py --- app/database/database.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/database/database.py b/app/database/database.py index 4646e282..51b8d427 100644 --- a/app/database/database.py +++ b/app/database/database.py @@ -2,7 +2,7 @@ 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 QueuePool from app.config import settings from app.database.models import Base @@ -11,7 +11,11 @@ logger = logging.getLogger(__name__) engine = create_async_engine( settings.get_database_url(), - poolclass=NullPool, + poolclass=QueuePool, + pool_size=20, + max_overflow=30, + pool_pre_ping=True, + pool_recycle=300, echo=settings.DEBUG, future=True ) From f76114d7dc8ed9694d8ca89ae8f9f8a3c63b6995 Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 9 Nov 2025 08:17:43 +0300 Subject: [PATCH 2/4] Update database.py --- app/database/database.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/database/database.py b/app/database/database.py index 51b8d427..4646e282 100644 --- a/app/database/database.py +++ b/app/database/database.py @@ -2,7 +2,7 @@ import logging from typing import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker -from sqlalchemy.pool import QueuePool +from sqlalchemy.pool import NullPool from app.config import settings from app.database.models import Base @@ -11,11 +11,7 @@ logger = logging.getLogger(__name__) engine = create_async_engine( settings.get_database_url(), - poolclass=QueuePool, - pool_size=20, - max_overflow=30, - pool_pre_ping=True, - pool_recycle=300, + poolclass=NullPool, echo=settings.DEBUG, future=True ) From cde84ff20bb004b619315a9ab2a6f0728ebfff27 Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 9 Nov 2025 08:23:01 +0300 Subject: [PATCH 3/4] Handle optional Pal24 metadata fields --- app/database/database.py | 7 +++++-- app/services/payment/pal24.py | 20 ++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/database/database.py b/app/database/database.py index 4646e282..9282dcc3 100644 --- a/app/database/database.py +++ b/app/database/database.py @@ -2,16 +2,19 @@ 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 AsyncAdaptedQueuePool from app.config import settings from app.database.models import Base logger = logging.getLogger(__name__) +QueuePool = AsyncAdaptedQueuePool + + engine = create_async_engine( settings.get_database_url(), - poolclass=NullPool, + poolclass=QueuePool, echo=settings.DEBUG, future=True ) 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): From a72bb25ea2ab3150235b65e34d7e2371e5a98a24 Mon Sep 17 00:00:00 2001 From: Egor Date: Sun, 9 Nov 2025 08:30:38 +0300 Subject: [PATCH 4/4] Update database.py --- app/database/database.py | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/app/database/database.py b/app/database/database.py index 9282dcc3..db591002 100644 --- a/app/database/database.py +++ b/app/database/database.py @@ -1,30 +1,47 @@ import logging from typing import AsyncGenerator - from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker -from sqlalchemy.pool import AsyncAdaptedQueuePool - +from sqlalchemy.pool import NullPool, AsyncAdaptedQueuePool from app.config import settings from app.database.models import Base logger = logging.getLogger(__name__) -QueuePool = AsyncAdaptedQueuePool - +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=QueuePool, + 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, ) @@ -36,8 +53,6 @@ async def get_db() -> AsyncGenerator[AsyncSession, None]: except Exception: await session.rollback() raise - finally: - await session.close() async def init_db():