diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 33dcf978854..91bbc418ffd 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -5717,7 +5717,6 @@ def _with_config_file_pass_through_endpoints( def _reload_settings_store(section: Section, store: SettingsStore, section_config: object) -> None: serving_pass_throughs: Final = store.get("pass_through_endpoints") store.load_yaml(_as_settings_mapping(section_config)) - store.apply_db_row(section, _EMPTY_SETTINGS_MAPPING) if is_resource_list(section, "pass_through_endpoints") and serving_pass_throughs is not None: store["pass_through_endpoints"] = serving_pass_throughs @@ -6540,6 +6539,9 @@ class ProxyConfig: prisma_client=prisma_client, store_model_in_db=store_model_in_db, ) + else: + for section, store in self._settings_stores.items(): + store.apply_db_row(section, _EMPTY_SETTINGS_MAPPING) config = self._config_with_resolved_settings(config) @@ -8623,12 +8625,24 @@ class ProxyConfig: environment_read: Final = next(self._environment_read_numbers) sections: Final = tuple(self._settings_stores) responses: Final = await asyncio.gather(*(get_config_param(prisma_client, section) for section in sections)) + general_settings_response: Final = responses[sections.index("general_settings")] + general_settings_value: Final[Mapping[str, SettingsJsonValue]] = ( + self._prepared_db_settings_values("general_settings", general_settings_response.param_value) + if general_settings_response is not None and general_settings_response.param_value is not None + else _EMPTY_SETTINGS_MAPPING + ) + self._settings_stores["general_settings"].apply_db_row("general_settings", general_settings_value) + response: _ConfigParamValueRow | None for section, response in zip(sections, responses): + if section == "general_settings": + continue if response is None: + self._settings_stores[section].apply_db_row(section, _EMPTY_SETTINGS_MAPPING) continue param_value: JsonValue = getattr(response, "param_value", None) if param_value is None: + self._settings_stores[section].apply_db_row(section, _EMPTY_SETTINGS_MAPPING) continue verbose_proxy_logger.debug( @@ -8639,6 +8653,7 @@ class ProxyConfig: if section == "litellm_settings": self._apply_litellm_settings_db_values(self._prepared_db_settings_values(section, param_value)) elif section == "environment_variables": + self._settings_stores[section].apply_db_row(section, _EMPTY_SETTINGS_MAPPING) await self._apply_db_environment_variables_row( prisma_client, response, environment_before_db, environment_read ) diff --git a/tests/unit/proxy/proxy_server/test_proxy_config.py b/tests/unit/proxy/proxy_server/test_proxy_config.py index a78209e16fe..55226fc629b 100644 --- a/tests/unit/proxy/proxy_server/test_proxy_config.py +++ b/tests/unit/proxy/proxy_server/test_proxy_config.py @@ -32,11 +32,13 @@ import litellm from litellm._logging import turn_on_json from litellm.proxy._types import CommonProxyErrors, ConfigGeneralSettings from litellm.proxy.common_utils.encrypt_decrypt_utils import encrypt_value_helper +from litellm.proxy.config_resolvers.settings_store import SettingsStore from litellm.router_api import ApplyResult, RouterSettings from litellm.types.router import Deployment, LiteLLM_Params from litellm.proxy.proxy_server import ( ProxyConfig, _is_remote_module_url, + _reload_settings_store, _scrub_db_overlay_remote_module_loads, _scrub_guardrail_inner, resolve_complexity_router_plugins, @@ -70,6 +72,15 @@ def _db_model(model_id: str, model_name: str = "gpt-3.5-turbo") -> SimpleNamespa ) +def test_yaml_settings_reload_keeps_db_general_settings_until_sync() -> None: + settings: Final = SettingsStore("general_settings") + settings.apply_db_row("general_settings", {"max_file_downloads_per_minute": 2}) + + _reload_settings_store("general_settings", settings, {}) + + assert settings["max_file_downloads_per_minute"] == 2 + + @pytest.mark.asyncio async def test_proxy_config_adds_and_deletes_stale_deployment(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: from litellm.proxy import proxy_server