fix(bot): eliminate duplicate review cards caused by sync race and edit fallback
This commit is contained in:
@@ -81,21 +81,27 @@ async def get_by_prefix(draft_prefix: str, chat_id: int | None = None) -> BotDra
|
|||||||
|
|
||||||
async def save_payload(draft: BotDraft, missing: dict | None = None,
|
async def save_payload(draft: BotDraft, missing: dict | None = None,
|
||||||
review_message_id: int | None = None,
|
review_message_id: int | None = None,
|
||||||
source_message_id: int | None = None) -> None:
|
source_message_id: int | None = None,
|
||||||
|
mark_bale_synced: bool = False) -> None:
|
||||||
async with SessionLocal() as session:
|
async with SessionLocal() as session:
|
||||||
|
effective_review_msg_id = review_message_id if review_message_id is not None else draft.review_message_id
|
||||||
values: dict = {
|
values: dict = {
|
||||||
"payload": draft.payload,
|
"payload": draft.payload,
|
||||||
"missing": missing,
|
"missing": missing,
|
||||||
"review_message_id": review_message_id or draft.review_message_id,
|
"review_message_id": effective_review_msg_id,
|
||||||
}
|
}
|
||||||
if source_message_id:
|
if source_message_id is not None:
|
||||||
values["source_message_id"] = source_message_id
|
values["source_message_id"] = source_message_id
|
||||||
|
draft.source_message_id = source_message_id
|
||||||
|
if mark_bale_synced:
|
||||||
|
values["last_bale_update_at"] = func.now()
|
||||||
await session.execute(
|
await session.execute(
|
||||||
update(BotDraft)
|
update(BotDraft)
|
||||||
.where(BotDraft.id == draft.id)
|
.where(BotDraft.id == draft.id)
|
||||||
.values(**values)
|
.values(**values)
|
||||||
)
|
)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
draft.review_message_id = effective_review_msg_id
|
||||||
|
|
||||||
|
|
||||||
async def set_status(draft_id: str, status: str) -> None:
|
async def set_status(draft_id: str, status: str) -> None:
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ async def handle_entities(
|
|||||||
if target_draft is not None:
|
if target_draft is not None:
|
||||||
draft = target_draft
|
draft = target_draft
|
||||||
prev_review_msg_id = draft.review_message_id
|
prev_review_msg_id = draft.review_message_id
|
||||||
|
draft.review_message_id = None
|
||||||
payload = draft.payload
|
payload = draft.payload
|
||||||
merge_quote_patch(payload, patch)
|
merge_quote_patch(payload, patch)
|
||||||
draft.source_message_id = incoming_msg_id
|
draft.source_message_id = incoming_msg_id
|
||||||
@@ -36,11 +37,6 @@ async def handle_entities(
|
|||||||
)
|
)
|
||||||
|
|
||||||
await resolve_payload(ctx, payload)
|
await resolve_payload(ctx, payload)
|
||||||
await draft_store.save_payload(
|
|
||||||
draft,
|
|
||||||
missing={"fields": compute_quote_missing(payload)},
|
|
||||||
source_message_id=incoming_msg_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
if prev_review_msg_id:
|
if prev_review_msg_id:
|
||||||
try:
|
try:
|
||||||
@@ -213,11 +209,23 @@ async def render(ctx, chat_id, draft, fresh: bool = True, note: str | None = Non
|
|||||||
missing={"fields": missing},
|
missing={"fields": missing},
|
||||||
review_message_id=new_review_id,
|
review_message_id=new_review_id,
|
||||||
source_message_id=reply_to or draft.source_message_id,
|
source_message_id=reply_to or draft.source_message_id,
|
||||||
|
mark_bale_synced=True,
|
||||||
)
|
)
|
||||||
await draft_store.set_bale_updated_at(draft.id)
|
|
||||||
else:
|
else:
|
||||||
await ctx.edit(chat_id, draft.review_message_id, text, reply_markup=keyboard)
|
await draft_store.save_payload(
|
||||||
await draft_store.save_payload(draft, missing={"fields": missing})
|
draft,
|
||||||
|
missing={"fields": missing},
|
||||||
|
source_message_id=reply_to or draft.source_message_id,
|
||||||
|
mark_bale_synced=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if not draft.review_message_id:
|
||||||
|
return
|
||||||
|
success = await ctx.edit(chat_id, draft.review_message_id, text, reply_markup=keyboard)
|
||||||
|
if success:
|
||||||
|
await draft_store.save_payload(draft, missing={"fields": missing}, mark_bale_synced=True)
|
||||||
|
else:
|
||||||
|
logger.warning("Could not edit review message %s for draft %s", draft.review_message_id, draft.id)
|
||||||
await draft_store.set_bale_updated_at(draft.id)
|
await draft_store.set_bale_updated_at(draft.id)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -129,14 +129,15 @@ class BotContext:
|
|||||||
return message
|
return message
|
||||||
|
|
||||||
async def edit(self, chat_id: int, message_id: int | None, text: str,
|
async def edit(self, chat_id: int, message_id: int | None, text: str,
|
||||||
reply_markup: dict | None = None) -> None:
|
reply_markup: dict | None = None) -> bool:
|
||||||
if not message_id:
|
if not message_id:
|
||||||
await self.send(chat_id, text, reply_markup=reply_markup)
|
return False
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
await self.bale.edit_message_text(chat_id, message_id, text, reply_markup=reply_markup)
|
await self.bale.edit_message_text(chat_id, message_id, text, reply_markup=reply_markup)
|
||||||
except Exception:
|
return True
|
||||||
await self.send(chat_id, text, reply_markup=reply_markup)
|
except Exception as exc:
|
||||||
|
logger.warning("failed to edit message %s in chat %s: %s", message_id, chat_id, exc)
|
||||||
|
return False
|
||||||
|
|
||||||
async def delete(self, chat_id: int, message_id: int | None) -> bool:
|
async def delete(self, chat_id: int, message_id: int | None) -> bool:
|
||||||
if not message_id:
|
if not message_id:
|
||||||
|
|||||||
Reference in New Issue
Block a user