mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-05 08:07:05 +00:00
fix(router): return None instead of raising ValueError in least-busy strategy
- Replace raise ValueError with return None when no healthy deployments are available, matching the None-return contract used by lowest_tpm and lowest_latency strategies; the router's `if deployment is None` path then raises the proper RouterRateLimitError with cooldown context - Add Optional[dict] return type annotation to _get_available_deployments - Add test_should_return_none_when_no_healthy_deployments to cover the None-return path - Seed random.seed(42) in probabilistic distribution tests for reproducible CI runs Made-with: Cursor
This commit is contained in:
parent
7df4a236f4
commit
f69fa5aca1
2 changed files with 18 additions and 4 deletions
|
|
@ -193,9 +193,11 @@ class LeastBusyLoggingHandler(CustomLogger):
|
|||
self,
|
||||
healthy_deployments: list,
|
||||
all_deployments: dict,
|
||||
):
|
||||
) -> Optional[dict]:
|
||||
"""
|
||||
Helper to get deployments using least busy strategy
|
||||
Helper to get deployments using least busy strategy.
|
||||
Returns None when no healthy deployments are available, consistent
|
||||
with other routing strategies (lowest_tpm, lowest_latency).
|
||||
"""
|
||||
healthy_ids = set()
|
||||
for d in healthy_deployments:
|
||||
|
|
@ -216,14 +218,14 @@ class LeastBusyLoggingHandler(CustomLogger):
|
|||
min_deployment_ids.append(k)
|
||||
|
||||
if not min_deployment_ids:
|
||||
raise ValueError("No healthy deployments available")
|
||||
return None
|
||||
|
||||
chosen_id = random.choice(min_deployment_ids)
|
||||
for m in healthy_deployments:
|
||||
if m["model_info"]["id"] == chosen_id:
|
||||
return m
|
||||
|
||||
raise ValueError(f"Chosen deployment id {chosen_id!r} not found in healthy_deployments")
|
||||
return None
|
||||
|
||||
def get_available_deployments(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import random
|
||||
import sys
|
||||
from collections import Counter
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ class TestLeastBusyTieBreaking:
|
|||
"""Tests that least-busy strategy distributes requests across tied deployments."""
|
||||
|
||||
def test_should_randomly_distribute_when_all_counts_are_zero(self):
|
||||
random.seed(42)
|
||||
cache = DualCache()
|
||||
handler = LeastBusyLoggingHandler(router_cache=cache)
|
||||
deployments = [_make_deployment(i) for i in range(3)]
|
||||
|
|
@ -44,6 +46,7 @@ class TestLeastBusyTieBreaking:
|
|||
)
|
||||
|
||||
def test_should_randomly_distribute_when_counts_are_tied(self):
|
||||
random.seed(42)
|
||||
cache = DualCache()
|
||||
handler = LeastBusyLoggingHandler(router_cache=cache)
|
||||
deployments = [_make_deployment(i) for i in range(2)]
|
||||
|
|
@ -65,6 +68,15 @@ class TestLeastBusyTieBreaking:
|
|||
f"Deployment {dep_id} selected only {count}/200 times — distribution is too skewed"
|
||||
)
|
||||
|
||||
def test_should_return_none_when_no_healthy_deployments(self):
|
||||
cache = DualCache()
|
||||
handler = LeastBusyLoggingHandler(router_cache=cache)
|
||||
|
||||
result = handler._get_available_deployments(
|
||||
healthy_deployments=[], all_deployments={}
|
||||
)
|
||||
assert result is None
|
||||
|
||||
def test_should_pick_unique_minimum(self):
|
||||
cache = DualCache()
|
||||
handler = LeastBusyLoggingHandler(router_cache=cache)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue