fix(webhook): avoid MissingGreenlet on expired ORM instance after commit
Release / release (push) Successful in 58s
Release / release (push) Successful in 58s
Telegram webhook handler crashed with sqlalchemy.exc.MissingGreenlet
when processing any incoming message after committing the chat row:
TelegramChat.bot_id == bot.id
^^^^^^
MissingGreenlet: greenlet_spawn has not been called
AsyncSession expires all instances on commit. Accessing bot.id/bot.token
after that triggers implicit lazy-load I/O from a sync attribute getter,
which can't enter the greenlet dispatcher → crash.
Fix: snapshot bot.id + bot.token to locals before commit, refresh the
ORM instance after a successful commit so handle_command() can still
use it, and route the remaining call sites through the snapshot
variables.
This commit is contained in:
@@ -71,9 +71,15 @@ async def telegram_webhook(
|
||||
# Auto-persist chat from incoming message
|
||||
from_user = message.get("from", {})
|
||||
msg_language = from_user.get("language_code", "")
|
||||
# Snapshot bot identity before commit — AsyncSession expires instances
|
||||
# on commit, and implicit lazy-load of `bot.id` / `bot.token` later would
|
||||
# raise sqlalchemy.exc.MissingGreenlet.
|
||||
bot_id = bot.id
|
||||
bot_token = bot.token
|
||||
try:
|
||||
await save_chat_from_webhook(session, bot.id, chat_info, language_code=msg_language)
|
||||
await save_chat_from_webhook(session, bot_id, chat_info, language_code=msg_language)
|
||||
await session.commit()
|
||||
await session.refresh(bot)
|
||||
except Exception:
|
||||
_LOGGER.warning("Failed to auto-save chat %s", chat_id, exc_info=True)
|
||||
|
||||
@@ -81,7 +87,7 @@ async def telegram_webhook(
|
||||
if text.startswith("/"):
|
||||
chat_row = (await session.exec(
|
||||
select(TelegramChat).where(
|
||||
TelegramChat.bot_id == bot.id,
|
||||
TelegramChat.bot_id == bot_id,
|
||||
TelegramChat.chat_id == chat_id,
|
||||
)
|
||||
)).first()
|
||||
@@ -93,9 +99,9 @@ async def telegram_webhook(
|
||||
if responses:
|
||||
for resp in responses:
|
||||
if resp.text:
|
||||
await send_reply(bot.token, chat_id, resp.text, reply_to_message_id=message_id)
|
||||
await send_reply(bot_token, chat_id, resp.text, reply_to_message_id=message_id)
|
||||
if resp.media:
|
||||
await send_media_group(bot.token, chat_id, resp.media, reply_to_message_id=message_id)
|
||||
await send_media_group(bot_token, chat_id, resp.media, reply_to_message_id=message_id)
|
||||
return {"ok": True}
|
||||
|
||||
return {"ok": True, "skipped": "not_a_command"}
|
||||
|
||||
Reference in New Issue
Block a user