test(router): completion(), anthropic_messages() and the sync responses() retry a 503 the same way

This commit is contained in:
devin-ai-integration[bot] 2026-11-08 02:03:20 +00:00
parent f9cb19ee04
commit e1cd2cf201

View file

@ -1,11 +1,13 @@
from __future__ import annotations
import asyncio
import uuid
from collections.abc import Callable
from typing import Final
from integration._support.anthropic_sse import Attempts
from integration._support.openai_wire import openai_error, posted_targets, responses_reply
import pytest
from integration._support.anthropic_sse import Attempts, message_json
from integration._support.openai_wire import chat_reply, openai_error, posted_targets, responses_reply
from integration._support.wire import Reply, Request, wire_server
from litellm import Router
from litellm.types.llms.openai import ResponsesAPIResponse
@ -13,13 +15,14 @@ from litellm.types.router import DeploymentTypedDict
_MODEL: Final = "gpt-5.4"
_API_KEY: Final = "sync-responses-retry-test-key"
_CLAUDE: Final = "claude-sonnet-4-5"
_TEXT: Final = "served after the blip"
def _deployment(model_name: str, api_base: str) -> DeploymentTypedDict:
def _deployment(model_name: str, api_base: str, model: str = f"openai/{_MODEL}") -> DeploymentTypedDict:
return DeploymentTypedDict(
model_name=model_name,
litellm_params={"model": f"openai/{_MODEL}", "api_base": api_base, "api_key": _API_KEY},
litellm_params={"model": model, "api_base": api_base, "api_key": _API_KEY},
)
@ -28,10 +31,18 @@ def _upstream(fails: Callable[[str, int], bool]) -> Callable[[Request], Reply]:
def respond(request: Request) -> Reply:
group, _, route = request.target.lstrip("/").partition("/")
assert (request.method, route) == ("POST", "responses"), request
assert request.method == "POST", request
if fails(group, attempts.record(group)):
return openai_error(503)
return responses_reply(f"resp_{group}_{uuid.uuid4().hex}", _MODEL, _TEXT, stream=False)
identity: Final = f"{group}_{uuid.uuid4().hex}"
match route:
case "responses":
return responses_reply(f"resp_{identity}", _MODEL, _TEXT, stream=False)
case "chat/completions":
return chat_reply(f"chatcmpl-{identity}", _MODEL, _TEXT, stream=False)
case "v1/messages":
return Reply(body=message_json(f"msg_{identity}", _CLAUDE, _TEXT))
raise AssertionError(request)
return respond
@ -72,3 +83,44 @@ def test_sync_responses_falls_back_when_the_primary_group_keeps_failing() -> Non
assert _output_text(response) == _TEXT
assert targets == ("/primary/responses", "/backup/responses")
@pytest.mark.parametrize(
("model", "route", "call"),
[
pytest.param(
f"openai/{_MODEL}",
"/my-model/chat/completions",
lambda router: router.completion(model="my-model", messages=[{"role": "user", "content": "hi"}]),
id="completion",
),
pytest.param(
f"anthropic/{_CLAUDE}",
"/my-model/v1/messages",
lambda router: asyncio.run(
router.anthropic_messages(model="my-model", messages=[{"role": "user", "content": "hi"}], max_tokens=16)
),
id="anthropic_messages",
),
pytest.param(
f"openai/{_MODEL}",
"/my-model/responses",
lambda router: router.responses(model="my-model", input="hi"),
id="responses",
),
],
)
def test_every_entry_point_retries_the_group_after_a_503_the_same_way(
model: str, route: str, call: Callable[[Router], object]
) -> None:
with wire_server(_upstream(lambda _group, attempt: attempt == 1)) as wire:
router: Final = Router(
model_list=[_deployment("my-model", f"{wire.url}/my-model", model)],
num_retries=1,
retry_after=0,
disable_cooldowns=True,
)
_ = call(router)
targets: Final = posted_targets(wire)
assert targets == (route, route)