Files
onGuard24/onguard24/domain/events.py

79 lines
2.2 KiB
Python
Raw Normal View History

"""События домена и подписка модулей (задел; пока in-memory)."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Protocol
from uuid import UUID
from onguard24.domain.entities import Alert
@dataclass
class DomainEvent:
"""Базовый тип события."""
name: str = "domain.generic"
occurred_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
@dataclass
class AlertReceived(DomainEvent):
"""Алерт принят в систему (после нормализации)."""
name: str = "alert.received"
alert: Alert | None = None
raw_payload_ref: UUID | None = None
grafana_org_slug: str | None = None
service_name: str | None = None
Handler = Callable[[DomainEvent], Awaitable[None]]
class Module(Protocol):
"""Модуль (schedules, contacts, …) может подписаться на события."""
@property
def name(self) -> str: ...
async def on_event(self, event: DomainEvent) -> None: ...
class EventBus(Protocol):
async def publish(self, event: DomainEvent) -> None: ...
def subscribe(self, event_name: str, handler: Handler) -> None: ...
class InMemoryEventBus:
"""Простая шина для тестов и раннего прототипа."""
def __init__(self) -> None:
self._subs: dict[str, list[Handler]] = {}
def subscribe(self, event_name: str, handler: Handler) -> None:
self._subs.setdefault(event_name, []).append(handler)
async def publish(self, event: DomainEvent) -> None:
for h in self._subs.get(event.name, []):
await h(event)
async def publish_alert_received(
self,
alert: Alert,
raw_payload_ref: UUID | None = None,
*,
grafana_org_slug: str | None = None,
service_name: str | None = None,
) -> None:
ev = AlertReceived(
alert=alert,
raw_payload_ref=raw_payload_ref,
grafana_org_slug=grafana_org_slug,
service_name=service_name,
)
await self.publish(ev)