feat: add core modules (config, state, diff, apply, health)

This commit is contained in:
2026-06-11 22:50:58 +02:00
parent a4e86e837c
commit ae1cbe27a4
5 changed files with 442 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
import json
import threading
from datetime import datetime, timezone
from http.server import HTTPServer, BaseHTTPRequestHandler
from io import StringIO
class HealthServer:
def __init__(self, port: int = 8081):
self.port = port
self.lock = threading.Lock()
self.last_sync = None
self.last_sync_duration = 0.0
self.last_sync_success = None
self.event_count = 0
self.syncs_total = 0
self.syncs_failed = 0
self.server = None
self.thread = None
def start(self) -> None:
handler = self._make_handler()
self.server = HTTPServer(("0.0.0.0", self.port), handler)
self.thread = threading.Thread(target=self.server.serve_forever, daemon=True)
self.thread.start()
def stop(self) -> None:
if self.server:
self.server.shutdown()
self.server = None
self.thread = None
def update_status(self, last_sync: datetime, duration: float, success: bool, event_count: int) -> None:
with self.lock:
self.last_sync = last_sync
self.last_sync_duration = duration
self.last_sync_success = success
self.event_count = event_count
self.syncs_total += 1
if not success:
self.syncs_failed += 1
def _make_handler(self):
server_self = self
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/health":
self._handle_health(server_self)
elif self.path == "/metrics":
self._handle_metrics(server_self)
else:
self.send_response(404)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"error": "not found"}).encode())
def _handle_health(self, srv):
with srv.lock:
status = "ok"
result = "none"
if srv.last_sync_success is not None:
if srv.last_sync_success:
result = "success"
else:
result = "failure"
status = "error"
payload = {
"status": status,
"last_sync": srv.last_sync.isoformat() if srv.last_sync else None,
"last_sync_duration_sec": srv.last_sync_duration,
"last_sync_result": result,
"event_count": srv.event_count,
"syncs_total": srv.syncs_total,
"syncs_failed": srv.syncs_failed,
}
body = json.dumps(payload).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(body)
def _handle_metrics(self, srv):
with srv.lock:
last_success = 1 if srv.last_sync_success else 0
duration = srv.last_sync_duration
evt_count = srv.event_count
total = srv.syncs_total
failed = srv.syncs_failed
buf = StringIO()
buf.write(f"baikal_sync_last_duration_seconds {duration}\n")
buf.write(f"baikal_sync_events_total {evt_count}\n")
buf.write(f"baikal_sync_total {total}\n")
buf.write(f"baikal_sync_failures_total {failed}\n")
buf.write(f"baikal_sync_last_success {last_success}\n")
body = buf.getvalue().encode()
self.send_response(200)
self.send_header("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
pass
return Handler