Skip to content

Commit d7c5196

Browse files
committed
fix(main): use atomic insert ON CONFLICT for webhook idempotency
1 parent f64fb85 commit d7c5196

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

main.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,18 @@ async def telegram_webhook(token: str, request: Request):
121121
update = telegram.Update.de_json(data=data, bot=application.bot)
122122

123123
# Idempotency check: Have we processed this update_id already?
124+
# Using an atomic insert to prevent race conditions when multiple Cloud Run
125+
# instances receive the same update simultaneously.
126+
from sqlalchemy.dialects.postgresql import insert
124127
with get_session() as session:
125-
existing = session.query(ProcessedUpdate).filter_by(update_id=update.update_id).first()
126-
if existing:
128+
stmt = insert(ProcessedUpdate).values(update_id=update.update_id).on_conflict_do_nothing()
129+
result = session.execute(stmt)
130+
session.commit()
131+
132+
# If rowcount is 0, the record already existed and ON CONFLICT prevented insertion
133+
if result.rowcount == 0:
127134
logging.getLogger("DCUBABOT").info(f"Skipping duplicate update_id {update.update_id}")
128135
return Response(status_code=200)
129-
130-
# If not, mark as processed and commit immediately
131-
session.add(ProcessedUpdate(update_id=update.update_id))
132-
session.commit()
133136

134137
# Await the processing SYNCHRONOUSLY before returning 200 OK
135138
# This prevents Cloud Run from throttling the CPU while the bot is doing work

0 commit comments

Comments
 (0)