mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
fix(proxy): propagate the caching flag across workers via the safe-override allowlist
enable_anthropic_prompt_caching and anthropic_prompt_caching_ttl are set as live litellm attributes on the worker that handles the UI save, exactly like budget_exceeded_throttle_percentage, but they were missing from LITELLM_SETTINGS_SAFE_DB_OVERRIDES, so a peer worker's config reload merged the DB value without applying it to the live attribute and stayed stale. Add both to the allowlist so they behave like the sibling field, and add test_general_settings_ui_fields_are_db_overridable so the UI registry and the override allowlist cannot drift again (the exact omission that caused this), plus a regression test that the flag flips on a simulated peer-worker reload.
This commit is contained in:
parent
4e5f488452
commit
47ba9e7612
2 changed files with 51 additions and 0 deletions
|
|
@ -1517,6 +1517,12 @@ LITELLM_SETTINGS_SAFE_DB_OVERRIDES = [
|
|||
"cost_discount_config",
|
||||
"cost_margin_config",
|
||||
"budget_exceeded_throttle_percentage",
|
||||
# Every field editable from the Admin UI (proxy_server._GENERAL_SETTINGS_UI_LITELLM_FIELDS)
|
||||
# must be listed here so a DB write from one worker overrides the live litellm attribute on
|
||||
# the others when config reloads; otherwise peer workers stay on their startup value.
|
||||
# test_general_settings_ui_fields_are_db_overridable enforces that pairing.
|
||||
"enable_anthropic_prompt_caching",
|
||||
"anthropic_prompt_caching_ttl",
|
||||
]
|
||||
SPECIAL_LITELLM_AUTH_TOKEN = ["ui-token"]
|
||||
DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL = int(os.getenv("DEFAULT_MANAGEMENT_OBJECT_IN_MEMORY_CACHE_TTL", 60))
|
||||
|
|
|
|||
|
|
@ -9029,6 +9029,51 @@ def test_get_config_list_includes_anthropic_prompt_caching_fields(monkeypatch):
|
|||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_general_settings_ui_fields_are_db_overridable():
|
||||
"""Every field the Admin UI can edit is a `litellm.<attr>` set via setattr on the handling
|
||||
worker (`_persist_general_settings_ui_litellm_field`). Unless it is also in
|
||||
LITELLM_SETTINGS_SAFE_DB_OVERRIDES, a config reload on a peer worker merges the DB value but
|
||||
never applies it to the live attribute, so peer workers stay on their startup value.
|
||||
|
||||
This invariant is the guard against the two registries drifting: adding a UI-editable field
|
||||
without enrolling it in the DB-override allowlist silently breaks cross-worker propagation.
|
||||
"""
|
||||
from litellm.constants import LITELLM_SETTINGS_SAFE_DB_OVERRIDES
|
||||
from litellm.proxy.proxy_server import _GENERAL_SETTINGS_UI_LITELLM_FIELDS
|
||||
|
||||
missing = set(_GENERAL_SETTINGS_UI_LITELLM_FIELDS) - set(LITELLM_SETTINGS_SAFE_DB_OVERRIDES)
|
||||
assert not missing, (
|
||||
f"UI-editable litellm_settings fields missing from LITELLM_SETTINGS_SAFE_DB_OVERRIDES: {sorted(missing)}. "
|
||||
"Add them, or they will not propagate to other workers when changed from the UI."
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"field_name, db_value",
|
||||
[
|
||||
("enable_anthropic_prompt_caching", True),
|
||||
("anthropic_prompt_caching_ttl", "1h"),
|
||||
],
|
||||
)
|
||||
def test_prompt_caching_settings_propagate_on_config_reload(monkeypatch, field_name, db_value):
|
||||
"""A UI toggle on one worker persists to the DB; a peer worker picks it up only when the
|
||||
config reload applies the safe-override allowlist. Regression for the fields being absent
|
||||
from that allowlist, which left peer workers stale."""
|
||||
import litellm.proxy.proxy_server as ps
|
||||
|
||||
# peer worker booted with the opposite/absent value
|
||||
monkeypatch.setattr(litellm, field_name, False if isinstance(db_value, bool) else None)
|
||||
|
||||
pc = ps.ProxyConfig()
|
||||
pc._update_config_fields(
|
||||
current_config={"litellm_settings": {}},
|
||||
param_name="litellm_settings",
|
||||
db_param_value={field_name: db_value},
|
||||
)
|
||||
|
||||
assert getattr(litellm, field_name) == db_value
|
||||
|
||||
|
||||
def test_get_config_list_marks_untouched_prompt_caching_flag_as_not_set(monkeypatch):
|
||||
"""The flag defaults to False rather than None, so a plain 'is not None' check would
|
||||
report the default as 'In Config' and imply an admin had set it."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue