Skip to content

Commit 7eedb88

Browse files
committed
fix(inference_store): on duplicate chat completion IDs, replace
1 parent c04f1c1 commit 7eedb88

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

llama_stack/providers/utils/inference/inference_store.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# the root directory of this source tree.
66
import asyncio
77
from typing import Any
8+
from sqlalchemy.exc import IntegrityError
89

910
from llama_stack.apis.inference import (
1011
ListOpenAIChatCompletionResponse,
@@ -129,16 +130,44 @@ async def _write_chat_completion(
129130
raise ValueError("Inference store is not initialized")
130131

131132
data = chat_completion.model_dump()
132-
133-
await self.sql_store.insert(
134-
table="chat_completions",
135-
data={
136-
"id": data["id"],
137-
"created": data["created"],
138-
"model": data["model"],
139-
"choices": data["choices"],
140-
"input_messages": [message.model_dump() for message in input_messages],
141-
},
133+
record_data = {
134+
"id": data["id"],
135+
"created": data["created"],
136+
"model": data["model"],
137+
"choices": data["choices"],
138+
"input_messages": [message.model_dump() for message in input_messages],
139+
}
140+
141+
try:
142+
await self.sql_store.insert(
143+
table="chat_completions",
144+
data=record_data,
145+
)
146+
except IntegrityError as e:
147+
# Check if it's a unique constraint violation
148+
error_message = str(e.orig) if e.orig else str(e)
149+
if self._is_unique_constraint_error(error_message):
150+
# Update the existing record instead
151+
await self.sql_store.update(
152+
table="chat_completions",
153+
data=record_data,
154+
where={"id": data["id"]}
155+
)
156+
else:
157+
# Re-raise if it's not a unique constraint error
158+
raise
159+
160+
def _is_unique_constraint_error(self, error_message: str) -> bool:
161+
"""Check if the error is specifically a unique constraint violation."""
162+
error_lower = error_message.lower()
163+
return any(
164+
indicator in error_lower
165+
for indicator in [
166+
"unique constraint failed", # SQLite
167+
"duplicate key", # PostgreSQL
168+
"unique violation", # PostgreSQL alternative
169+
"duplicate entry", # MySQL
170+
]
142171
)
143172

144173
async def list_chat_completions(

llama_stack/providers/utils/sqlstore/authorized_sqlstore.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ async def fetch_one(
172172

173173
return results.data[0] if results.data else None
174174

175+
async def update(self, table: str, data: Mapping[str, Any], where: Mapping[str, Any]) -> None:
176+
"""Update rows with automatic access control attribute capture."""
177+
enhanced_data = dict(data)
178+
179+
current_user = get_authenticated_user()
180+
if current_user:
181+
enhanced_data["owner_principal"] = current_user.principal
182+
enhanced_data["access_attributes"] = current_user.attributes
183+
else:
184+
enhanced_data["owner_principal"] = None
185+
enhanced_data["access_attributes"] = None
186+
187+
await self.sql_store.update(table, enhanced_data, where)
188+
175189
async def delete(self, table: str, where: Mapping[str, Any]) -> None:
176190
"""Delete rows with automatic access control filtering."""
177191
await self.sql_store.delete(table, where)

0 commit comments

Comments
 (0)