WIP autoscaler agent

This commit is contained in:
Abel Luck 2026-02-27 11:59:16 +01:00
parent c610a3e284
commit 28059dcedf
34 changed files with 2409 additions and 35 deletions

View file

@ -0,0 +1,39 @@
"""Injectable clock abstraction for testability."""
from __future__ import annotations
from datetime import UTC, datetime, timedelta
from typing import Protocol
class Clock(Protocol):
"""Clock protocol — provides current UTC time."""
def now(self) -> datetime: ...
class SystemClock:
"""Real wall-clock implementation."""
def now(self) -> datetime:
"""Return the current UTC time."""
return datetime.now(UTC)
class FakeClock:
"""Deterministic clock for tests."""
def __init__(self, start: datetime | None = None) -> None:
self._now = start or datetime(2026, 1, 1, tzinfo=UTC)
def now(self) -> datetime:
"""Return the fixed current time."""
return self._now
def advance(self, seconds: float) -> None:
"""Advance the clock by the given number of seconds."""
self._now += timedelta(seconds=seconds)
def set(self, dt: datetime) -> None:
"""Set the clock to an exact time."""
self._now = dt

View file

@ -0,0 +1,54 @@
"""HAProxy runtime socket adapter — stub for Plan 02."""
from __future__ import annotations
from dataclasses import dataclass
class HAProxyError(Exception):
"""Error communicating with HAProxy runtime socket."""
@dataclass
class SlotHealth:
"""Health status for a single HAProxy server slot."""
status: str
scur: int
qcur: int
class HAProxyRuntime:
"""HAProxy runtime CLI adapter via Unix socket.
Full implementation in Plan 02.
"""
def __init__(self, socket_path: str, backend: str, slot_prefix: str) -> None:
self._socket_path = socket_path
self._backend = backend
self._slot_prefix = slot_prefix
def set_slot_addr(self, slot_id: str, ip: str, port: int = 22) -> None:
"""Update server address for a slot."""
raise NotImplementedError
def enable_slot(self, slot_id: str) -> None:
"""Enable a server slot."""
raise NotImplementedError
def disable_slot(self, slot_id: str) -> None:
"""Disable a server slot."""
raise NotImplementedError
def slot_is_up(self, slot_id: str) -> bool:
"""Return True when HAProxy health status is UP for slot."""
raise NotImplementedError
def slot_session_count(self, slot_id: str) -> int:
"""Return current active session count for slot."""
raise NotImplementedError
def read_slot_health(self) -> dict[str, SlotHealth]:
"""Return full stats snapshot for all slots."""
raise NotImplementedError