This commit is contained in:
Timothy Jaeryang Baek
2026-05-19 20:37:53 +04:00
parent c75fe8e74b
commit aa06200f78
3 changed files with 49 additions and 0 deletions
@@ -394,6 +394,24 @@ class ChatMessageTable:
await db.commit()
return True
async def delete_message_ids_by_chat_id(
self,
chat_id: str,
message_ids: set[str],
db: Optional[AsyncSession] = None,
) -> bool:
"""Delete specific ``chat_message`` rows by their original message IDs."""
if not message_ids:
return True
async with get_async_db_context(db) as db:
await db.execute(
delete(ChatMessage)
.where(ChatMessage.chat_id == chat_id)
.where(ChatMessage.id.in_({f'{chat_id}-{mid}' for mid in message_ids}))
)
await db.commit()
return True
# Analytics methods
async def get_message_count_by_model(
self,
+23
View File
@@ -394,6 +394,9 @@ class ChatTable:
try:
async with get_async_db_context(db) as db:
chat_item = await db.get(Chat, id)
if chat_item is None:
return None
chat_item.chat = self._clean_null_bytes(chat)
chat_item.title = self._clean_null_bytes(chat['title']) if 'title' in chat else 'New Chat'
@@ -495,6 +498,26 @@ class ChatTable:
except Exception as e:
log.warning('Backfill failed for message %s in chat %s: %s', message_id, chat_id, e)
async def reconcile_messages_by_chat_id(
self, chat_id: str, user_id: str, messages: dict[str, dict]
) -> None:
"""Sync ``chat_message`` rows with the committed JSON blob.
Upserts current messages via ``backfill_messages_by_chat_id``
and deletes orphaned rows whose message_id no longer appears
in the blob. Best-effort: errors are logged but never raised.
"""
try:
await self.backfill_messages_by_chat_id(chat_id, user_id, messages)
existing_map = await ChatMessages.get_messages_map_by_chat_id(chat_id)
if existing_map is not None:
orphaned_ids = set(existing_map.keys()) - set(messages.keys())
if orphaned_ids:
await ChatMessages.delete_message_ids_by_chat_id(chat_id, orphaned_ids)
except Exception as e:
log.warning('Failed to reconcile chat_message rows for chat %s: %s', chat_id, e)
async def get_messages_map_by_chat_id(self, id: str) -> dict | None:
"""Message map for walking history (see ``get_message_list``).
+8
View File
@@ -987,6 +987,14 @@ async def update_chat_by_id(
msg['content'] = serialize_output(msg['output'])
chat = await Chats.update_chat_by_id(id, updated_chat, db=db)
# Reconcile chat_message rows with the committed blob.
# This is the only caller where the frontend pushes a full
# history with potential edits, deletions, or new branches.
messages = (updated_chat.get('history') or {}).get('messages') or {}
if messages:
await Chats.reconcile_messages_by_chat_id(id, user.id, messages)
return ChatResponse(**chat.model_dump())
else:
raise HTTPException(