Source code for ralph.process.liveness

"""LivenessProbe protocol and implementations for aggregate-tree idle evaluation.

The LivenessProbe is an injectable seam so unit tests can fake agent-tree
activity without spawning real processes.
"""

from __future__ import annotations

from ralph.process._default_liveness_probe import DefaultLivenessProbe
from ralph.process._liveness_probe import LivenessProbe
from ralph.process.child_liveness import ChildActivitySnapshot


[docs] class FakeLivenessProbe: """Test-only probe that returns a fixed activity answer. When ``active_labels`` is provided the probe simulates a specific set of active process labels: ``any_agent_active(prefix)`` returns True only when at least one label in ``active_labels`` starts with ``prefix``. This lets tests distinguish between related and unrelated agent workers. When ``active_labels`` is None the probe falls back to the flat ``active`` flag (existing behaviour, unchanged). When ``snapshot`` is provided, child_snapshot() returns it for any prefix. """ def __init__( self, *, active: bool = False, active_labels: frozenset[str] | None = None, snapshot: ChildActivitySnapshot | None = None, ) -> None: self._active = active self._active_labels = active_labels self._snapshot = snapshot def any_agent_active(self, label_prefix: str) -> bool: if self._active_labels is not None: return any(label.startswith(label_prefix) for label in self._active_labels) return self._active def child_snapshot(self, scope_prefix: str) -> ChildActivitySnapshot: if self._snapshot is not None: return self._snapshot # For empty prefix with label-based matching, don't scan labels. # Mirrors DefaultLivenessProbe which skips label scanning for empty # scope_prefix to avoid false matches against the parent process. if not scope_prefix and self._active_labels is not None: active = False else: active = self.any_agent_active(scope_prefix) return ChildActivitySnapshot( scope_prefix=scope_prefix, has_process=active, has_fresh_label=active, has_fresh_progress=active, oldest_live_child_seconds=None, active_count=1 if active else 0, terminal_count=0, )
__all__ = [ "DefaultLivenessProbe", "FakeLivenessProbe", "LivenessProbe", ]