From 06d9ef286850cc14b49b55deddbe1bb438e26913 Mon Sep 17 00:00:00 2001 From: zosimovaa Date: Thu, 26 Feb 2026 22:47:42 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D1=82=D0=B0=D0=B9?= =?UTF-8?q?=D0=BC=D0=B0=D1=83=D1=82=D0=B0=20healthy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 ++-- src/config_manager/v2/core/manager.py | 28 ++++++++++++++++++++++++--- tests/v2/test_health_timeout.py | 26 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 tests/v2/test_health_timeout.py diff --git a/pyproject.toml b/pyproject.toml index b1bd994..0a560dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta" [project] name = "config_manager" -version = "2.2.3" -description = "Большой рефакторинг, логирование" +version = "2.2.4" +description = "Фикс таймаута healthy" authors = [ { name = "Aleksei Zosimov", email = "lesha.spb@gmail.com" } ] diff --git a/src/config_manager/v2/core/manager.py b/src/config_manager/v2/core/manager.py index c6100e0..4b77832 100644 --- a/src/config_manager/v2/core/manager.py +++ b/src/config_manager/v2/core/manager.py @@ -55,6 +55,27 @@ def _read_env_optional_float(name: str, default_value: Optional[float]) -> Optio return default_value +def _read_env_health_timeout(default_value: float) -> float: + """Read health timeout from env.""" + env_name = "HEALTH_TIMEOUT" + raw_value = os.environ.get(env_name) + if raw_value is None: + return default_value + try: + parsed = float(raw_value) + if parsed <= 0: + raise ValueError(f"{env_name} must be greater than zero") + return parsed + except Exception: # noqa: BLE001 + logger.exception( + "ConfigManagerV2 health timeout parse error: env=%s raw_value=%s fallback=%s", + env_name, + raw_value, + default_value, + ) + return default_value + + class _RuntimeController: """Runtime loops and lifecycle supervision.""" @@ -311,7 +332,7 @@ class ConfigManagerV2(_RuntimeController): DEFAULT_UPDATE_INTERVAL = 5 DEFAULT_WORK_INTERVAL = 2 - DEFAULT_HEALTH_TIMEOUT = 30 + DEFAULT_HEALTH_TIMEOUT = 90 DEFAULT_EXECUTE_TIMEOUT = 600.0 def __init__( @@ -346,7 +367,7 @@ class ConfigManagerV2(_RuntimeController): initial_config = self._loader.load_sync() self.config = initial_config - self._health_timeout = self.DEFAULT_HEALTH_TIMEOUT + self._health_timeout = _read_env_health_timeout(float(self.DEFAULT_HEALTH_TIMEOUT)) self._health_aggregator = HealthAggregator( get_state=lambda: self._state, get_last_error=lambda: self._last_execute_error, @@ -367,11 +388,12 @@ class ConfigManagerV2(_RuntimeController): else: self._control_channels = list(control_channels) self.logger.debug( - "ConfigManagerV2.__init__ result: path=%s update_interval=%s work_interval=%s execute_timeout=%s control_channels=%s", + "ConfigManagerV2.__init__ result: path=%s update_interval=%s work_interval=%s execute_timeout=%s health_timeout=%s control_channels=%s", self.path, self.update_interval, self.work_interval, self._execute_timeout, + self._health_timeout, len(self._control_channels), ) diff --git a/tests/v2/test_health_timeout.py b/tests/v2/test_health_timeout.py new file mode 100644 index 0000000..fa497f0 --- /dev/null +++ b/tests/v2/test_health_timeout.py @@ -0,0 +1,26 @@ +from config_manager.v2 import ConfigManagerV2 + + +class TimeoutApp(ConfigManagerV2): + def execute(self) -> None: + return + + +def test_health_timeout_uses_main_env_key(tmp_path, monkeypatch): + cfg = tmp_path / "config.yaml" + cfg.write_text("log: {}\nmanagement: { enabled: false }\nhealth_timeout: 150\n", encoding="utf-8") + monkeypatch.setenv("HEALTH_TIMEOUT", "120") + monkeypatch.setenv("HEALTHY_TIMEOUT", "300") + + app = TimeoutApp(str(cfg)) + assert app._health_timeout == 120.0 + + +def test_health_timeout_defaults_to_90_when_env_not_set(tmp_path, monkeypatch): + cfg = tmp_path / "config.yaml" + cfg.write_text("log: {}\nmanagement: { enabled: false }\nhealth_timeout: 150\n", encoding="utf-8") + monkeypatch.delenv("HEALTH_TIMEOUT", raising=False) + monkeypatch.delenv("HEALTHY_TIMEOUT", raising=False) + + app = TimeoutApp(str(cfg)) + assert app._health_timeout == 90.0