Files
checkbot/app/poller/loop.py
T
patrickandClaude Sonnet 5.5 5278530467
test / pytest (3.11) (push) Waiting to run
test / pytest (3.13) (push) Waiting to run
feat: Phase 6b rules with delay, delta format, reminders, zpool default rule
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-06 02:38:10 +01:00

72 lines
2.6 KiB
Python

import asyncio
import logging
import time
from typing import Awaitable, Callable
from ..checkmk import CheckmkClient
from ..models import Event
from ..routing import Route, delay_provider
from .events import compute_events
from .options import PollOptions, read_poll_options
from .state import StateStore
from .status import PollerStatus
log = logging.getLogger(__name__)
ERROR_MAX = 200
EventSink = Callable[[list[Event]], Awaitable[None]]
RuleSource = Callable[[], list[Route]]
class Poller:
def __init__(self, store, state: StateStore, sink: EventSink, status: PollerStatus,
client_factory: Callable[[], CheckmkClient | None] | None = None,
clock: Callable[[], float] = time.time, rules: RuleSource | None = None):
self._store = store
self._state = state
self._sink = sink
self.status = status
self._client_factory = client_factory or (lambda: CheckmkClient.from_settings(store))
self._clock = clock
self._rules = rules or (lambda: [])
async def run(self) -> None:
while True:
options = read_poll_options(self._store)
self.status.interval = options.interval
try:
await self.run_cycle(options)
except asyncio.CancelledError:
raise
except Exception:
log.exception("Poller-Zyklus fehlgeschlagen")
await asyncio.sleep(options.interval)
async def run_cycle(self, options: PollOptions | None = None) -> None:
options = options or read_poll_options(self._store)
client = self._client_factory()
if client is None:
return
try:
current = await client.problem_services()
except Exception as exc:
self.status.last_error = f"{type(exc).__name__}: {exc}"[:ERROR_MAX]
log.warning("Checkmk-Abfrage fehlgeschlagen: %s", self.status.last_error)
return
finally:
await client.aclose()
now = int(self._clock())
previous = await asyncio.to_thread(self._state.load)
rules = await asyncio.to_thread(self._rules)
delay = delay_provider(rules, options.default_delay_minutes)
events, rows = compute_events(previous, current, now, delay)
await asyncio.to_thread(self._state.apply, previous, rows, now)
self.status.last_success = self._clock()
self.status.last_error = None
if events:
try:
await self._sink(events)
except Exception:
log.exception("Verarbeitung der Events fehlgeschlagen")