mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-16 04:29:31 +00:00
* test(integration): cover responses endpoint contracts Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): tighten responses contract tests per review Isolate team-only response-id ownership with a same-user different-team key, send every denial through the OpenAI SDK on all three aliases, make the previous_response_id affinity check deterministic, assert the whole cancel response, prove the Cursor stream text, -fast suffixes and include_obfuscation strip, add SDK compact cases, restore router pre-call checks after the affinity test, and inline the root-level responses_test_support helpers Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): wait for every proxy worker before routing to new deployments Restore the cross-worker convergence wait dropped when the shared helper was inlined, so the affinity and retrieve-routing tests cannot pass before the alternative deployment is loaded on a multi-worker gateway Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): cover Responses ownership and wire contracts Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): address responses contract review Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): expect the provider model in the conversation passthrough body Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): expand responses endpoint contracts Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): restore streamed response retrieval Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): wait for proxy workers after deployment setup Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(integration): track readiness per proxy worker Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: mateo <mateo@berri.ai> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
64 lines
2.7 KiB
Python
64 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from collections.abc import Iterator, Mapping
|
|
from itertools import accumulate
|
|
from types import MappingProxyType
|
|
from typing import Final
|
|
|
|
import httpx
|
|
|
|
from integration._support.client import Gateway, JSON_OBJECT, object_value
|
|
from litellm.constants import PROXY_CONFIG_RELOAD_INTERVAL_SECONDS
|
|
|
|
|
|
def _record_latest_readback(
|
|
latest_by_worker: Mapping[int, int],
|
|
observation: tuple[int, int],
|
|
) -> Mapping[int, int]:
|
|
worker_pid, count = observation
|
|
return MappingProxyType({**latest_by_worker, worker_pid: count})
|
|
|
|
|
|
def wait_for_worker_readiness(
|
|
gateway: Gateway,
|
|
group: str,
|
|
deployments: int,
|
|
workers: int,
|
|
) -> None:
|
|
deadline: Final = time.monotonic() + (30 if workers == 1 else PROXY_CONFIG_RELOAD_INTERVAL_SECONDS * 2 + 30)
|
|
headers: Final = {"Authorization": f"Bearer {gateway.key}"}
|
|
|
|
def readbacks() -> Iterator[tuple[int, int]]:
|
|
while time.monotonic() < deadline:
|
|
timeout: Final = deadline - time.monotonic()
|
|
with httpx.Client(
|
|
base_url=str(gateway.client.base_url),
|
|
timeout=timeout,
|
|
trust_env=False,
|
|
verify=False,
|
|
) as client:
|
|
debug_response: Final = client.get("/debug/memory/summary", headers=headers)
|
|
response: Final = client.get(
|
|
"/model/info",
|
|
headers=headers,
|
|
)
|
|
assert debug_response.status_code == 200, debug_response.text
|
|
assert response.status_code == 200, response.text
|
|
assert debug_response.extensions.get("network_stream") is not None
|
|
assert debug_response.extensions.get("network_stream") is response.extensions.get("network_stream")
|
|
debug_body: Final = JSON_OBJECT.validate_json(debug_response.content)
|
|
worker_pid: Final = debug_body.get("worker_pid")
|
|
assert isinstance(worker_pid, int), debug_body
|
|
body: Final = JSON_OBJECT.validate_json(response.content)
|
|
entries: Final = body.get("data")
|
|
assert isinstance(entries, list), body
|
|
count: Final = sum(object_value(entry).get("model_name") == group for entry in entries)
|
|
yield worker_pid, count
|
|
|
|
initial_counts: Final[Mapping[int, int]] = MappingProxyType({})
|
|
latest_counts: Final = accumulate(readbacks(), _record_latest_readback, initial=initial_counts)
|
|
for latest_by_worker in latest_counts:
|
|
if len(latest_by_worker) >= workers and all(count == deployments for count in latest_by_worker.values()):
|
|
return
|
|
raise AssertionError(f"Expected {deployments} deployments on {workers} workers before the readiness deadline")
|