mirror of
https://github.com/open-webui/open-webui.git
synced 2026-03-09 07:18:29 -05:00
fix: add deterministic tiebreaker to all paginated chat queries (#22387)
Add Chat.id as a secondary sort key to all paginated chat queries that use offset/limit pagination. When multiple chats share the same updated_at timestamp, the database does not guarantee a stable order across page boundaries, causing chats to appear on multiple pages. This produces duplicate keys in the Svelte sidebar each-block (each_key_duplicate error). Adding Chat.id as a tiebreaker ensures fully deterministic ordering. Extends the fix from #22383 (which addressed get_chat_ids_by_model_id) to all remaining paginated chat queries.
This commit is contained in:
@@ -734,13 +734,13 @@ class ChatTable:
|
||||
raise ValueError("Invalid order_by field")
|
||||
|
||||
if direction.lower() == "asc":
|
||||
query = query.order_by(getattr(Chat, order_by).asc())
|
||||
query = query.order_by(getattr(Chat, order_by).asc(), Chat.id)
|
||||
elif direction.lower() == "desc":
|
||||
query = query.order_by(getattr(Chat, order_by).desc())
|
||||
query = query.order_by(getattr(Chat, order_by).desc(), Chat.id)
|
||||
else:
|
||||
raise ValueError("Invalid direction for ordering")
|
||||
else:
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
query = query.with_entities(
|
||||
Chat.id, Chat.title, Chat.updated_at, Chat.created_at
|
||||
@@ -793,13 +793,13 @@ class ChatTable:
|
||||
raise ValueError("Invalid order_by field")
|
||||
|
||||
if direction.lower() == "asc":
|
||||
query = query.order_by(getattr(Chat, order_by).asc())
|
||||
query = query.order_by(getattr(Chat, order_by).asc(), Chat.id)
|
||||
elif direction.lower() == "desc":
|
||||
query = query.order_by(getattr(Chat, order_by).desc())
|
||||
query = query.order_by(getattr(Chat, order_by).desc(), Chat.id)
|
||||
else:
|
||||
raise ValueError("Invalid direction for ordering")
|
||||
else:
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
# Select only the columns needed for SharedChatResponse
|
||||
# to avoid loading the heavy chat JSON blob
|
||||
@@ -854,13 +854,13 @@ class ChatTable:
|
||||
|
||||
if order_by and direction and getattr(Chat, order_by):
|
||||
if direction.lower() == "asc":
|
||||
query = query.order_by(getattr(Chat, order_by).asc())
|
||||
query = query.order_by(getattr(Chat, order_by).asc(), Chat.id)
|
||||
elif direction.lower() == "desc":
|
||||
query = query.order_by(getattr(Chat, order_by).desc())
|
||||
query = query.order_by(getattr(Chat, order_by).desc(), Chat.id)
|
||||
else:
|
||||
raise ValueError("Invalid direction for ordering")
|
||||
else:
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
if skip:
|
||||
query = query.offset(skip)
|
||||
@@ -892,7 +892,7 @@ class ChatTable:
|
||||
if not include_archived:
|
||||
query = query.filter_by(archived=False)
|
||||
|
||||
query = query.order_by(Chat.updated_at.desc()).with_entities(
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id).with_entities(
|
||||
Chat.id, Chat.title, Chat.updated_at, Chat.created_at
|
||||
)
|
||||
|
||||
@@ -1039,14 +1039,14 @@ class ChatTable:
|
||||
if order_by and direction:
|
||||
if hasattr(Chat, order_by):
|
||||
if direction.lower() == "asc":
|
||||
query = query.order_by(getattr(Chat, order_by).asc())
|
||||
query = query.order_by(getattr(Chat, order_by).asc(), Chat.id)
|
||||
elif direction.lower() == "desc":
|
||||
query = query.order_by(getattr(Chat, order_by).desc())
|
||||
query = query.order_by(getattr(Chat, order_by).desc(), Chat.id)
|
||||
else:
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
else:
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
total = query.count()
|
||||
|
||||
@@ -1188,7 +1188,7 @@ class ChatTable:
|
||||
if folder_ids:
|
||||
query = query.filter(Chat.folder_id.in_(folder_ids))
|
||||
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
# Check if the database dialect is either 'sqlite' or 'postgresql'
|
||||
dialect_name = db.bind.dialect.name
|
||||
@@ -1309,7 +1309,7 @@ class ChatTable:
|
||||
query = query.filter(or_(Chat.pinned == False, Chat.pinned == None))
|
||||
query = query.filter_by(archived=False)
|
||||
|
||||
query = query.order_by(Chat.updated_at.desc())
|
||||
query = query.order_by(Chat.updated_at.desc(), Chat.id)
|
||||
|
||||
if skip:
|
||||
query = query.offset(skip)
|
||||
|
||||
Reference in New Issue
Block a user