SFM/app/db/base.py
2026-10-09 17:35:36 +03:00

49 lines
2.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase
from app.core.config import settings
# Без явных таймаутов зависший/протухший сокет к Postgres (например, тихо
# оборванное NAT/LB соединение после долгого простоя — ровно то, что могло
# случиться во время получасовой обработки батча из 230 файлов) блокирует
# asyncpg НАВСЕГДА: ни ошибки, ни лога, просто вечное ожидание чтения
# сокета. Это тот же класс проблемы с asyncio.run()-за-asyncio.run() вокруг
# общего пула соединений, что уже ловили раньше (см. комментарий про
# engine.dispose() в opencloud_token_store.py) — тут решаем его с другой
# стороны: даём зависшему соединению упасть с понятной ошибкой вместо
# бесконечного ожидания.
_CONNECT_TIMEOUT_SECONDS = 10
_COMMAND_TIMEOUT_SECONDS = 15
connect_args: dict = {}
if settings.DATABASE_SCHEMA:
connect_args["server_settings"] = {"search_path": settings.DATABASE_SCHEMA}
if "sqlite" in settings.DATABASE_URL:
connect_args["check_same_thread"] = False
else:
# timeout/command_timeout — параметры asyncpg.connect(), не SQLAlchemy;
# aiosqlite их не понимает, поэтому только для не-sqlite URL.
connect_args["timeout"] = _CONNECT_TIMEOUT_SECONDS
connect_args["command_timeout"] = _COMMAND_TIMEOUT_SECONDS
engine = create_async_engine(
settings.DATABASE_URL,
pool_pre_ping=True,
pool_size=5,
max_overflow=10,
pool_timeout=_CONNECT_TIMEOUT_SECONDS,
connect_args=connect_args,
)
SessionLocal = async_sessionmaker(
bind=engine,
autoflush=False,
expire_on_commit=False,
)
class Base(AsyncAttrs, DeclarativeBase):
pass