WIP autoscaler agent
This commit is contained in:
parent
c610a3e284
commit
28059dcedf
34 changed files with 2409 additions and 35 deletions
0
agent/nix_builder_autoscaler/providers/__init__.py
Normal file
0
agent/nix_builder_autoscaler/providers/__init__.py
Normal file
39
agent/nix_builder_autoscaler/providers/clock.py
Normal file
39
agent/nix_builder_autoscaler/providers/clock.py
Normal 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
|
||||
54
agent/nix_builder_autoscaler/providers/haproxy.py
Normal file
54
agent/nix_builder_autoscaler/providers/haproxy.py
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue