fix: use SAVEPOINT instead of full rollback in sync user creation
Full db.rollback() in _get_or_create_bot_user_from_panel expires ALL ORM objects in the session, causing MissingGreenlet errors when subsequent sync iterations access user attributes from synchronous code. Replace with begin_nested() (SAVEPOINT) so only the failed INSERT is rolled back while the parent transaction and all cached objects remain valid.
This commit is contained in:
@@ -502,19 +502,18 @@ class RemnaWaveService:
|
||||
language='ru',
|
||||
)
|
||||
|
||||
db_user = await create_user_no_commit(**create_kwargs)
|
||||
# Используем SAVEPOINT чтобы при IntegrityError откатить только
|
||||
# вложенную транзакцию, а не всю сессию. Полный rollback помечает
|
||||
# ВСЕ объекты сессии как expired, что вызывает MissingGreenlet
|
||||
# при последующем sync-доступе к атрибутам ORM-объектов.
|
||||
async with db.begin_nested():
|
||||
db_user = await create_user_no_commit(**create_kwargs)
|
||||
return db_user, True
|
||||
except IntegrityError as create_error:
|
||||
logger.info(
|
||||
'♻️ Пользователь с telegram_id уже существует. Используем существующую запись.', telegram_id=telegram_id
|
||||
)
|
||||
|
||||
try:
|
||||
await db.rollback()
|
||||
except Exception:
|
||||
# create_user_no_commit уже выполняет rollback при необходимости
|
||||
pass
|
||||
|
||||
try:
|
||||
existing_user = await get_user_by_telegram_id(db, telegram_id)
|
||||
if existing_user is None:
|
||||
@@ -535,13 +534,11 @@ class RemnaWaveService:
|
||||
)
|
||||
return None, False
|
||||
except Exception as general_error:
|
||||
# SAVEPOINT (begin_nested) уже откатил частичную работу.
|
||||
# Полный rollback не нужен — он бы пометил все объекты сессии expired.
|
||||
logger.error(
|
||||
'❌ Общая ошибка создания/загрузки пользователя', telegram_id=telegram_id, general_error=general_error
|
||||
)
|
||||
try:
|
||||
await db.rollback()
|
||||
except:
|
||||
pass
|
||||
return None, False
|
||||
|
||||
async def get_system_statistics(self) -> dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user