mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-22 08:24:12 +00:00
[Fix] Block proxy startup when use_redis_transaction_buffer is enabled without Redis cache
When `use_redis_transaction_buffer: true` is set in general_settings but no Redis cache is configured in litellm_settings, the proxy starts successfully but silently drops all spend tracking data. This adds a startup validation that raises a clear error, preventing the proxy from running in a broken state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
b314e8d20a
commit
3a15e1cc2e
@@ -871,6 +871,12 @@ async def proxy_startup_event(app: FastAPI): # noqa: PLR0915
|
||||
redis_usage_cache=redis_usage_cache,
|
||||
)
|
||||
|
||||
## Validate use_redis_transaction_buffer requires Redis cache ##
|
||||
ProxyStartupEvent._validate_redis_transaction_buffer_config(
|
||||
general_settings=general_settings,
|
||||
redis_usage_cache=redis_usage_cache,
|
||||
)
|
||||
|
||||
## SEMANTIC TOOL FILTER ##
|
||||
# Read litellm_settings from config for semantic filter initialization
|
||||
try:
|
||||
@@ -5618,6 +5624,40 @@ class ProxyStartupEvent:
|
||||
llm_router=llm_router, redis_usage_cache=redis_usage_cache
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _validate_redis_transaction_buffer_config(
|
||||
general_settings: dict,
|
||||
redis_usage_cache: Optional[RedisCache],
|
||||
):
|
||||
"""
|
||||
Validates that when use_redis_transaction_buffer is enabled,
|
||||
a Redis cache is properly configured in litellm_settings.
|
||||
|
||||
Without Redis, spend updates are silently dropped because:
|
||||
- In-memory queues are drained but never pushed to Redis
|
||||
- The pod lock manager cannot acquire locks for DB commits
|
||||
- No fallback to direct DB writes occurs
|
||||
"""
|
||||
from litellm.proxy.db.db_transaction_queue.redis_update_buffer import (
|
||||
RedisUpdateBuffer,
|
||||
)
|
||||
|
||||
if (
|
||||
RedisUpdateBuffer._should_commit_spend_updates_to_redis()
|
||||
and redis_usage_cache is None
|
||||
):
|
||||
raise ValueError(
|
||||
"`use_redis_transaction_buffer` is enabled in general_settings, "
|
||||
"but no Redis cache is configured. Spend tracking will silently "
|
||||
"fail without Redis. Please add a Redis cache configuration in "
|
||||
"litellm_settings:\n\n"
|
||||
"litellm_settings:\n"
|
||||
" cache: true\n"
|
||||
" cache_params:\n"
|
||||
" type: redis\n"
|
||||
" url: os.environ/REDIS_URL\n"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def _initialize_semantic_tool_filter(
|
||||
cls,
|
||||
|
||||
@@ -10,6 +10,7 @@ sys.path.insert(
|
||||
) # Adds the parent directory to the system path
|
||||
|
||||
from litellm.proxy.db.db_transaction_queue.redis_update_buffer import RedisUpdateBuffer
|
||||
from litellm.proxy.proxy_server import ProxyStartupEvent
|
||||
from litellm.types.caching import RedisPipelineRpushOperation
|
||||
|
||||
|
||||
@@ -192,3 +193,53 @@ async def test_get_all_transactions_from_redis_buffer_pipeline_no_redis():
|
||||
buffer = RedisUpdateBuffer(redis_cache=None)
|
||||
result = await buffer.get_all_transactions_from_redis_buffer_pipeline()
|
||||
assert result == (None, None, None, None, None, None, None)
|
||||
|
||||
|
||||
def test_validate_redis_transaction_buffer_raises_without_redis():
|
||||
"""
|
||||
When use_redis_transaction_buffer=true but no Redis cache is configured,
|
||||
the proxy should refuse to start with a clear error message.
|
||||
"""
|
||||
general_settings = {"use_redis_transaction_buffer": True}
|
||||
|
||||
with patch(
|
||||
"litellm.proxy.proxy_server.general_settings", general_settings
|
||||
):
|
||||
with pytest.raises(ValueError, match="use_redis_transaction_buffer"):
|
||||
ProxyStartupEvent._validate_redis_transaction_buffer_config(
|
||||
general_settings=general_settings,
|
||||
redis_usage_cache=None,
|
||||
)
|
||||
|
||||
|
||||
def test_validate_redis_transaction_buffer_passes_with_redis():
|
||||
"""
|
||||
When use_redis_transaction_buffer=true and Redis cache is configured,
|
||||
validation should pass without error.
|
||||
"""
|
||||
general_settings = {"use_redis_transaction_buffer": True}
|
||||
mock_redis_cache = MagicMock()
|
||||
|
||||
with patch(
|
||||
"litellm.proxy.proxy_server.general_settings", general_settings
|
||||
):
|
||||
# Should not raise
|
||||
ProxyStartupEvent._validate_redis_transaction_buffer_config(
|
||||
general_settings=general_settings,
|
||||
redis_usage_cache=mock_redis_cache,
|
||||
)
|
||||
|
||||
|
||||
def test_validate_redis_transaction_buffer_passes_when_disabled():
|
||||
"""
|
||||
When use_redis_transaction_buffer is not set or false,
|
||||
validation should pass regardless of Redis configuration.
|
||||
"""
|
||||
with patch(
|
||||
"litellm.proxy.proxy_server.general_settings", {}
|
||||
):
|
||||
# Should not raise even without Redis
|
||||
ProxyStartupEvent._validate_redis_transaction_buffer_config(
|
||||
general_settings={},
|
||||
redis_usage_cache=None,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user