remove unnecessary logging
All checks were successful
Build Docs / changes (push) Successful in 4s
Build Docs / build-docs (push) Has been skipped
Build Docs / deploy-docs (push) Has been skipped

This commit is contained in:
Alexander Kalinovsky
2025-05-18 22:59:04 +07:00
parent 469b160fb8
commit b1f7ccf1b4
6 changed files with 18 additions and 52 deletions

View File

@@ -1,11 +1,9 @@
from typing import Annotated from fastapi import APIRouter, Request, Response, BackgroundTasks
from fastapi import APIRouter, Request, Response, BackgroundTasks, Depends
from fastapi.datastructures import State from fastapi.datastructures import State
from sqlmodel.ext.asyncio.session import AsyncSession
from ..main import QBotApp from ..main import QBotApp
from ..db import async_session, get_db from ..db import async_session
from aiogram.types import Update from aiogram.types import Update
from logging import getLogger from logging import getLogger
@@ -47,7 +45,7 @@ async def feed_bot_update(
update: Update, update: Update,
app_state: State, app_state: State,
): ):
async with get_db() as db_session: async with async_session() as db_session:
await app.dp.feed_webhook_update( await app.dp.feed_webhook_update(
bot=app.bot, bot=app.bot,
update=update, update=update,

View File

@@ -1,41 +1,16 @@
from contextlib import asynccontextmanager
from logging import getLogger
from typing import AsyncGenerator
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.ext.asyncio import create_async_engine from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from typing import AsyncGenerator
from ..config import config from ..config import config
logger = getLogger(__name__)
class TracedSession(AsyncSession):
def __del__(self):
logger.warning(f"💥 __del__ called — session was not properly closed! {id(self)}")
# This is a workaround for the issue with SQLAlchemy 2.0
# where the session is not closed properly and __del__ is called
# when the session is garbage collected.
# This is not a good practice, but it is a workaround for now
# to avoid the session being closed too early.
# You can also use the following line to print the stack trace
# to see where the session was created and not closed properly.
import traceback
traceback.print_stack()
async_engine = create_async_engine(config.DATABASE_URI, pool_size=20, max_overflow=60) async_engine = create_async_engine(config.DATABASE_URI, pool_size=20, max_overflow=60)
async_session = sessionmaker[AsyncSession]( async_session = sessionmaker[AsyncSession](
async_engine, class_=AsyncSession, expire_on_commit=False async_engine, class_=AsyncSession, expire_on_commit=False
) )
@asynccontextmanager
async def get_db() -> AsyncGenerator[AsyncSession, None]: async def get_db() -> AsyncGenerator[AsyncSession, None]:
session = async_session() async with async_session() as session:
logger.warning(f"🟢 Session created: {id(session)}")
try:
yield session yield session
finally:
await session.close()
logger.warning(f"❌ Session closed: {id(session)}")

View File

@@ -10,7 +10,7 @@ from sqlmodel import select
from typing import Any, Dict from typing import Any, Dict
import ujson as json import ujson as json
from ..db import async_session, get_db from ..db import async_session
from ..model.fsm_storage import FSMStorage from ..model.fsm_storage import FSMStorage
@@ -22,7 +22,7 @@ class DbStorage(BaseStorage):
async def set_state(self, key: StorageKey, state: StateType = None) -> None: async def set_state(self, key: StorageKey, state: StateType = None) -> None:
db_key = self.key_builder.build(key, "state") db_key = self.key_builder.build(key, "state")
async with get_db() as session: async with async_session() as session:
db_state = ( db_state = (
await session.exec(select(FSMStorage).where(FSMStorage.key == db_key)) await session.exec(select(FSMStorage).where(FSMStorage.key == db_key))
).first() ).first()
@@ -44,7 +44,7 @@ class DbStorage(BaseStorage):
async def get_state(self, key: StorageKey) -> str | None: async def get_state(self, key: StorageKey) -> str | None:
db_key = self.key_builder.build(key, "state") db_key = self.key_builder.build(key, "state")
async with get_db() as session: async with async_session() as session:
db_state = ( db_state = (
await session.exec(select(FSMStorage).where(FSMStorage.key == db_key)) await session.exec(select(FSMStorage).where(FSMStorage.key == db_key))
).first() ).first()
@@ -52,7 +52,7 @@ class DbStorage(BaseStorage):
async def set_data(self, key: StorageKey, data: Dict[str, Any]) -> None: async def set_data(self, key: StorageKey, data: Dict[str, Any]) -> None:
db_key = self.key_builder.build(key, "data") db_key = self.key_builder.build(key, "data")
async with get_db() as session: async with async_session() as session:
db_data = ( db_data = (
await session.exec(select(FSMStorage).where(FSMStorage.key == db_key)) await session.exec(select(FSMStorage).where(FSMStorage.key == db_key))
).first() ).first()
@@ -74,7 +74,7 @@ class DbStorage(BaseStorage):
async def get_data(self, key: StorageKey) -> Dict[str, Any]: async def get_data(self, key: StorageKey) -> Dict[str, Any]:
db_key = self.key_builder.build(key, "data") db_key = self.key_builder.build(key, "data")
async with get_db() as session: async with async_session() as session:
db_data = ( db_data = (
await session.exec(select(FSMStorage).where(FSMStorage.key == db_key)) await session.exec(select(FSMStorage).where(FSMStorage.key == db_key))
).first() ).first()

View File

@@ -19,7 +19,6 @@ from quickbot.utils.navigation import save_navigation_context
from .config import Config from .config import Config
from .bot.handlers.forms.entity_form import entity_item from .bot.handlers.forms.entity_form import entity_item
from .db import get_db
from .fsm.db_storage import DbStorage from .fsm.db_storage import DbStorage
from .middleware.telegram import AuthMiddleware, I18nMiddleware from .middleware.telegram import AuthMiddleware, I18nMiddleware
from .model.bot_entity import BotEntity from .model.bot_entity import BotEntity
@@ -187,7 +186,7 @@ class QBotApp(Generic[UserType, ConfigType], FastAPI):
user_id: int, user_id: int,
entity: type[BotEntity] | str, entity: type[BotEntity] | str,
entity_id: int, entity_id: int,
db_session: AsyncSession = None, db_session: AsyncSession,
form_name: str = None, form_name: str = None,
form_params: list[Any] = None, form_params: list[Any] = None,
): ):
@@ -217,9 +216,6 @@ class QBotApp(Generic[UserType, ConfigType], FastAPI):
) )
await state.set_data(state_data) await state.set_data(state_data)
if not db_session:
db_session = await get_db()
user = await self.user_class.get( user = await self.user_class.get(
session=db_session, session=db_session,
id=user_id, id=user_id,
@@ -244,7 +240,7 @@ class QBotApp(Generic[UserType, ConfigType], FastAPI):
app_state: State, app_state: State,
command: str, command: str,
user_id: int, user_id: int,
db_session: AsyncSession = None, db_session: AsyncSession,
): ):
state = self.dp.fsm.get_context(bot=self.bot, chat_id=user_id, user_id=user_id) state = self.dp.fsm.get_context(bot=self.bot, chat_id=user_id, user_id=user_id)
state_data = await state.get_data() state_data = await state.get_data()
@@ -255,9 +251,6 @@ class QBotApp(Generic[UserType, ConfigType], FastAPI):
command_name = command.split("&")[0] command_name = command.split("&")[0]
cmd = self.bot_commands.get(command_name) cmd = self.bot_commands.get(command_name)
if not db_session:
db_session = await get_db()
user = await self.user_class.get( user = await self.user_class.get(
session=db_session, session=db_session,
id=user_id, id=user_id,

View File

@@ -4,7 +4,7 @@ from sqlalchemy.orm.state import InstanceState
from typing import cast from typing import cast
from .bot_enum import BotEnum, EnumMember from .bot_enum import BotEnum, EnumMember
from ..db import async_session, get_db from ..db import async_session
class EntityPermission(BotEnum): class EntityPermission(BotEnum):
@@ -33,7 +33,7 @@ def session_dep(func):
_session = state.async_session _session = state.async_session
if not _session: if not _session:
async with get_db() as session: async with async_session() as session:
kwargs["session"] = session kwargs["session"] = session
return await func(cls, *args, **kwargs) return await func(cls, *args, **kwargs)
else: else:

View File

@@ -5,7 +5,7 @@ from sqlmodel import SQLModel, Field, select
from sqlmodel.ext.asyncio.session import AsyncSession from sqlmodel.ext.asyncio.session import AsyncSession
from typing import Any, get_args, get_origin from typing import Any, get_args, get_origin
from ..db import async_session, get_db from ..db import async_session
from .role import RoleBase from .role import RoleBase
from .descriptors import FieldDescriptor, Setting from .descriptors import FieldDescriptor, Setting
from ..utils.serialization import deserialize, serialize from ..utils.serialization import deserialize, serialize
@@ -205,7 +205,7 @@ class Settings(metaclass=SettingsMetaclass):
if name not in cls._cache.keys(): if name not in cls._cache.keys():
if session is None: if session is None:
async with get_db() as session: async with async_session() as session:
cls._cache[name] = await cls.load_param( cls._cache[name] = await cls.load_param(
session=session, param=param session=session, param=param
) )
@@ -272,7 +272,7 @@ class Settings(metaclass=SettingsMetaclass):
if isinstance(param, str): if isinstance(param, str):
param = cls._settings_descriptors[param] param = cls._settings_descriptors[param]
ser_value = serialize(value, param) ser_value = serialize(value, param)
async with get_db() as session: async with async_session() as session:
db_setting = ( db_setting = (
await session.exec( await session.exec(
select(DbSettings).where(DbSettings.name == param.field_name) select(DbSettings).where(DbSettings.name == param.field_name)