From 5c5b7796f46de7e72c9ee642e2ee12511bc4b57a Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2026 05:14:39 +0000 Subject: [PATCH] fix(redis): resolve Rust checks --- litellm-rust/crates/gateway/src/redis.rs | 4 +- litellm-rust/crates/python-bridge/src/lib.rs | 2 + .../crates/python-bridge/src/redis/events.rs | 45 ++++++++++++++----- .../crates/redis-connect/src/connect.rs | 4 +- litellm/rust_bridge/_native.pyi | 10 +++-- litellm/rust_bridge/host/redis_events.py | 6 +-- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/litellm-rust/crates/gateway/src/redis.rs b/litellm-rust/crates/gateway/src/redis.rs index 48794413d31..2bfa1da4ca4 100644 --- a/litellm-rust/crates/gateway/src/redis.rs +++ b/litellm-rust/crates/gateway/src/redis.rs @@ -1,8 +1,8 @@ use std::{sync::Arc, time::Duration}; use litellm_config::{ - CacheSettings, Config, RedisSettings, ResolvedRedis, SecretSnapshot, - Value, environment_has_target, + CacheSettings, Config, RedisSettings, ResolvedRedis, SecretSnapshot, Value, + environment_has_target, }; use litellm_core_utils::settings::Lookup; use litellm_redis_client::{RedisClient, RedisEvents}; diff --git a/litellm-rust/crates/python-bridge/src/lib.rs b/litellm-rust/crates/python-bridge/src/lib.rs index 31158e637ae..6491a416c3e 100644 --- a/litellm-rust/crates/python-bridge/src/lib.rs +++ b/litellm-rust/crates/python-bridge/src/lib.rs @@ -118,6 +118,8 @@ mod tests { "aresponses", "ResponsesWebSocketConnection", "NativeDiagnosticProcessor", + "NativeRouterCooldowns", + "NativeRouterUsage", "NativeClickHouseSpendConfig", "NativeClickHouseSpendStorage", "NativeDatabase", diff --git a/litellm-rust/crates/python-bridge/src/redis/events.rs b/litellm-rust/crates/python-bridge/src/redis/events.rs index a615c0829f3..fb64b942d53 100644 --- a/litellm-rust/crates/python-bridge/src/redis/events.rs +++ b/litellm-rust/crates/python-bridge/src/redis/events.rs @@ -51,9 +51,10 @@ impl ServiceLoggingEvents { }; runtime.spawn(async move { let reported = attach_blocking(context, move |py| match args { - ReportArgs::Call(call_type, duration, failure, caller) => { - record.bind(py).call1((call_type, duration.as_secs_f64(), failure, caller)).map(drop) - } + ReportArgs::Call(call_type, duration, failure, caller) => record + .bind(py) + .call1((call_type, duration.as_secs_f64(), failure, caller)) + .map(drop), ReportArgs::Breaker(state) => record.bind(py).call1((state,)).map(drop), }) .await @@ -102,12 +103,21 @@ impl RedisEvents for ServiceLoggingEvents { let caller = CALL.try_with(Clone::clone).ok(); let (context, call_type, caller) = match caller { Some(call) => (call.context, call.call_type, call.caller), - None => (self.context.clone(), operation_call_type(event.operation), None), + None => ( + self.context.clone(), + operation_call_type(event.operation), + None, + ), }; self.report( context, self.record_call.clone(), - ReportArgs::Call(call_type, event.duration, failure_label(event.outcome), caller), + ReportArgs::Call( + call_type, + event.duration, + failure_label(event.outcome), + caller, + ), ); } @@ -145,8 +155,13 @@ def record_redis_breaker(state): Python::initialize(); Python::attach(|py| { let name = std::ffi::CString::new(format!("redis_events_recorder_{name}")).unwrap(); - let module = PyModule::from_code(py, &std::ffi::CString::new(RECORDER).unwrap(), &name, &name).unwrap(); - (ServiceLoggingEvents::from_module(py, &module).unwrap(), module.unbind()) + let module = + PyModule::from_code(py, &std::ffi::CString::new(RECORDER).unwrap(), &name, &name) + .unwrap(); + ( + ServiceLoggingEvents::from_module(py, &module).unwrap(), + module.unbind(), + ) }) } @@ -205,9 +220,16 @@ def record_redis_breaker(state): ) { let (events, namespace) = recorder(expected); - events.breaker(&litellm_circuit_breaker::Transition { from: litellm_circuit_breaker::State::HalfOpen, to, generation: 1 }); + events.breaker(&litellm_circuit_breaker::Transition { + from: litellm_circuit_breaker::State::HalfOpen, + to, + generation: 1, + }); - assert_eq!(seen(&namespace, 1).await, format!("[('breaker', '{expected}')]")); + assert_eq!( + seen(&namespace, 1).await, + format!("[('breaker', '{expected}')]") + ); } #[rstest] @@ -221,6 +243,9 @@ def record_redis_breaker(state): outcome: Outcome::Succeeded, }); - assert_eq!(seen(&namespace, 1).await, "[('pipeline', 0.005, None, None, None)]"); + assert_eq!( + seen(&namespace, 1).await, + "[('pipeline', 0.005, None, None, None)]" + ); } } diff --git a/litellm-rust/crates/redis-connect/src/connect.rs b/litellm-rust/crates/redis-connect/src/connect.rs index 25b015baeb8..84aca8b5288 100644 --- a/litellm-rust/crates/redis-connect/src/connect.rs +++ b/litellm-rust/crates/redis-connect/src/connect.rs @@ -1,7 +1,9 @@ use std::sync::Arc; use litellm_circuit_breaker::{Breaker, Config as BreakerConfig}; -use litellm_config::{Expected, RedisAuth, RedisEndpoint, RedisError, RedisTls, ResolvedRedis, parse_seconds}; +use litellm_config::{ + Expected, RedisAuth, RedisEndpoint, RedisError, RedisTls, ResolvedRedis, parse_seconds, +}; use litellm_core_utils::settings::Lookup; use litellm_redis_client::{ ClusterEndpoint, ClusterNode, Credentials, CredentialsProvider, DEFAULT_TIMEOUT, Endpoint, diff --git a/litellm/rust_bridge/_native.pyi b/litellm/rust_bridge/_native.pyi index e4b39612f00..6f1c7b6b061 100644 --- a/litellm/rust_bridge/_native.pyi +++ b/litellm/rust_bridge/_native.pyi @@ -26,7 +26,7 @@ class NativeClickHouseSpendStorage: def ensure_schema(self) -> Future[None]: ... def insert_rows(self, rows: Sequence[Mapping[str, object]]) -> Future[None]: ... -class NativeCooldown(TypedDict): +class _NativeCooldown(TypedDict): exception_received: str status_code: str timestamp: float @@ -39,12 +39,12 @@ class NativeRouterCooldowns: ) -> NativeRouterCooldowns: ... def put(self, model_id: str, cooldown: Mapping[str, object], ttl_seconds: float) -> None: ... def increment_allowed_fails(self, model_id: str, suffix: str | None, ttl_seconds: float) -> int: ... - def active(self, model_ids: Sequence[str]) -> list[tuple[str, NativeCooldown]]: ... - def aactive(self, model_ids: Sequence[str]) -> Future[list[tuple[str, NativeCooldown]]]: ... + def active(self, model_ids: Sequence[str]) -> list[tuple[str, _NativeCooldown]]: ... + def aactive(self, model_ids: Sequence[str]) -> Future[list[tuple[str, _NativeCooldown]]]: ... def minimum(self, model_ids: Sequence[str]) -> float | None: ... def evict_local(self, model_id: str) -> None: ... def flush_local_counters(self) -> None: ... - def snapshot(self) -> dict[str, NativeCooldown]: ... + def snapshot(self) -> dict[str, _NativeCooldown]: ... @final class NativeRouterUsage: @@ -253,6 +253,8 @@ __all__ = [ "NativeClickHouseSpendStorage", "NativeDatabase", "NativeDiagnosticProcessor", + "NativeRouterCooldowns", + "NativeRouterUsage", "ProcessReservedForForking", "ResponsesWebSocketConnection", "RustBridgeDeclined", diff --git a/litellm/rust_bridge/host/redis_events.py b/litellm/rust_bridge/host/redis_events.py index b80a2158edd..202d43cd4fd 100644 --- a/litellm/rust_bridge/host/redis_events.py +++ b/litellm/rust_bridge/host/redis_events.py @@ -3,13 +3,13 @@ from __future__ import annotations from functools import lru_cache -from typing import Final, Literal +from typing import Final, Literal, TypeAlias from litellm._service_logger import ServiceLogging from litellm.types.services import ServiceTypes -Failure = Literal["timeout", "transport", "server", "decode", "breaker_open"] -BreakerState = Literal["closed", "open", "half_open"] +Failure: TypeAlias = Literal["timeout", "transport", "server", "decode", "breaker_open"] +BreakerState: TypeAlias = Literal["closed", "open", "half_open"] _HEALTH_FAILURE_CLASSES: Final = {"timeout": "timeout", "transport": "connectivity"}