mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
fix(internal_endpoints): only treat seq-collisions as 409 in events:append retry
The seq-collision retry in daemon_append_event previously caught all
Exception types and re-raised them as 409 event_seq_collision. A
transient DB error during retry would surface to the daemon as a
misleading 409, hiding the real outage and the daemon would respond
incorrectly (they treat 409 as 'data conflict, drop the event' rather
than 'retry').
Add a narrow _is_seq_collision predicate that matches:
* prisma.errors.UniqueViolationError (production)
* RuntimeError('event_seq_collision') marker (test stand-in)
Other errors bubble up unchanged so callers can distinguish a real
seq conflict from a real outage.
Greptile (review #PRR_kwDOKALCgc78u_NS — overly broad exception
catch in seq-collision retry).
This commit is contained in:
parent
164afd4a18
commit
124c73c1ed
1 changed files with 30 additions and 3 deletions
|
|
@ -50,6 +50,26 @@ def _now() -> datetime:
|
|||
return datetime.now(timezone.utc)
|
||||
|
||||
|
||||
def _is_seq_collision(exc: BaseException) -> bool:
|
||||
"""True iff ``exc`` is a (run_id, seq) unique-constraint violation.
|
||||
|
||||
We can't simply ``except prisma.errors.UniqueViolationError`` because
|
||||
the unit-test stand-in raises a plain ``RuntimeError("event_seq_collision")``,
|
||||
and we don't want the test path and prod path to diverge. Match
|
||||
either the Prisma class (when available) or our marker string.
|
||||
"""
|
||||
try:
|
||||
from prisma.errors import UniqueViolationError
|
||||
|
||||
if isinstance(exc, UniqueViolationError):
|
||||
return True
|
||||
except Exception:
|
||||
# Prisma unavailable in some test environments; fall through to
|
||||
# string-based detection.
|
||||
pass
|
||||
return "event_seq_collision" in str(exc)
|
||||
|
||||
|
||||
async def _get_prisma_client_or_503():
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
|
|
@ -250,9 +270,14 @@ async def daemon_append_event(
|
|||
}
|
||||
)
|
||||
except Exception as exc:
|
||||
# Most likely a (run_id, seq) unique-constraint collision. Reread
|
||||
# MAX(seq) and try once more — that's the defensive retry the
|
||||
# ticket calls out.
|
||||
# Treat only ``(run_id, seq)`` unique-constraint collisions as
|
||||
# retryable here; let any other error bubble up unchanged so
|
||||
# callers don't see a misleading 409 ``event_seq_collision``
|
||||
# for a transient DB outage. We detect collisions either via
|
||||
# the dedicated Prisma error class or — for unit tests using
|
||||
# an in-memory fake — a string match on the marker.
|
||||
if not _is_seq_collision(exc):
|
||||
raise
|
||||
last_evt = await prisma_client.db.litellm_agentrunevent.find_first(
|
||||
where={"run_id": run_id},
|
||||
order={"seq": "desc"},
|
||||
|
|
@ -268,6 +293,8 @@ async def daemon_append_event(
|
|||
}
|
||||
)
|
||||
except Exception as exc2:
|
||||
if not _is_seq_collision(exc2):
|
||||
raise
|
||||
verbose_proxy_logger.exception(
|
||||
"events:append double-collision run_id=%s: %s", run_id, exc2
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue