diff --git a/backend/src/config.py b/backend/src/config.py index 5cb20ab..cceb770 100644 --- a/backend/src/config.py +++ b/backend/src/config.py @@ -54,6 +54,7 @@ class BackendSettings: bridge_bpf_build_dir: str bridge_link_state_thread_join_timeout_seconds: float bridge_link_state_recovery_holdoff_seconds: float + bridge_link_state_degraded_recheck_seconds: float telemetry_process_stop_timeout_seconds: float telemetry_reader_join_timeout_seconds: float tshark_enabled: bool @@ -96,6 +97,10 @@ def load_settings() -> BackendSettings: "BACKEND_BRIDGE_LINK_STATE_RECOVERY_HOLDOFF_SECONDS", 1.0, ), + bridge_link_state_degraded_recheck_seconds=_env_float( + "BACKEND_BRIDGE_LINK_STATE_DEGRADED_RECHECK_SECONDS", + 0.5, + ), telemetry_process_stop_timeout_seconds=_env_float("BACKEND_TELEMETRY_PROCESS_STOP_TIMEOUT_SECONDS", 3.0), telemetry_reader_join_timeout_seconds=_env_float("BACKEND_TELEMETRY_READER_JOIN_TIMEOUT_SECONDS", 2.0), tshark_enabled=_env_bool("BACKEND_TSHARK_ENABLED", True), diff --git a/backend/src/utilities/bridge_link_state_manager.py b/backend/src/utilities/bridge_link_state_manager.py index 0e997ec..b67ad77 100644 --- a/backend/src/utilities/bridge_link_state_manager.py +++ b/backend/src/utilities/bridge_link_state_manager.py @@ -76,6 +76,7 @@ class BridgeLinkStateWatcher: self._suppressed_members: dict[str, bool] = {} self._settle_deadlines: dict[str, float] = {} self._all_clear_since: Optional[float] = None + self._degraded = False self._last_event_ts: Optional[float] = None self._last_error: Optional[str] = None self._last_action: Optional[str] = None @@ -126,6 +127,7 @@ class BridgeLinkStateWatcher: "last_action": self._last_action, "suppressed_members": sorted(self._suppressed_members), "recovery_holdoff_seconds": self.recovery_holdoff_seconds, + "degraded_recheck_seconds": settings.bridge_link_state_degraded_recheck_seconds, "members": members, } @@ -188,6 +190,7 @@ class BridgeLinkStateWatcher: if len(states) < 2: with self._lock: + self._degraded = False self._all_clear_since = None self._restore_suppressed_members(reason="bridge_has_fewer_than_two_members") return @@ -206,6 +209,7 @@ class BridgeLinkStateWatcher: if failing_members: with self._lock: + self._degraded = True self._all_clear_since = None self._suppress_other_members(states, failing_members) return @@ -213,6 +217,7 @@ class BridgeLinkStateWatcher: if suppressed_snapshot: should_restore = False with self._lock: + self._degraded = True if self._all_clear_since is None: self._all_clear_since = now should_restore = now - self._all_clear_since >= self.recovery_holdoff_seconds @@ -225,6 +230,7 @@ class BridgeLinkStateWatcher: return with self._lock: + self._degraded = False self._all_clear_since = None self._restore_suppressed_members(reason=reason) @@ -234,7 +240,12 @@ class BridgeLinkStateWatcher: with self._lock: if self._suppressed_members and self._all_clear_since is not None: deadline = self._all_clear_since + self.recovery_holdoff_seconds - return max(0.0, deadline - time.time()) + return max( + 0.0, + min(deadline - time.time(), settings.bridge_link_state_degraded_recheck_seconds), + ) + if self._degraded: + return settings.bridge_link_state_degraded_recheck_seconds return None def _wake_thread(self) -> None: