Files
patrickandClaude Sonnet 5.5 5278530467
test / pytest (3.11) (push) Canceled after 0s
test / pytest (3.13) (push) Canceled after 0s
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

54 lines
1.9 KiB
Python

import asyncio
import logging
import time
from typing import Awaitable, Callable
from ..models import Event, Key, StateRow
from ..mutes import Mute
from ..routing import Route
from .due import due_reminders
log = logging.getLogger(__name__)
CHECK_INTERVAL_SECONDS = 60.0
class ReminderWorker:
def __init__(self, load_state: Callable[[], dict[Key, StateRow]], rules: Callable[[], list[Route]],
mutes: Callable[[float], list[Mute]], default_hours: Callable[[], int],
sink: Callable[[list[Event]], Awaitable[None]], mark: Callable[[str, str, int], None],
clock: Callable[[], float] = time.time, interval: float = CHECK_INTERVAL_SECONDS,
sleep: Callable[[float], Awaitable[None]] = asyncio.sleep):
self._load = load_state
self._rules = rules
self._mutes = mutes
self._default_hours = default_hours
self._sink = sink
self._mark = mark
self._clock = clock
self._interval = interval
self._sleep = sleep
async def tick(self) -> int:
now = int(self._clock())
rows = await asyncio.to_thread(self._load)
rules = await asyncio.to_thread(self._rules)
mutes = await asyncio.to_thread(self._mutes, now)
events = due_reminders(rows.values(), rules, mutes, self._default_hours(), now)
for event in events:
# Zeitpunkt zuerst festhalten: lieber eine Erinnerung zu wenig als eine doppelte nach Neustart.
await asyncio.to_thread(self._mark, event.host, event.service, now)
if events:
await self._sink(events)
return len(events)
async def run(self) -> None:
while True:
try:
await self.tick()
except asyncio.CancelledError:
raise
except Exception:
log.exception("Erinnerungen: Prüfung fehlgeschlagen")
await self._sleep(self._interval)