diff --git a/src/monitor_service/models.py b/src/monitor_service/models.py new file mode 100644 index 0000000..84bd06b --- /dev/null +++ b/src/monitor_service/models.py @@ -0,0 +1,58 @@ +from datetime import datetime, timezone +from enum import Enum +from uuid import UUID + +from pydantic import BaseModel, ConfigDict, Field, HttpUrl, model_validator + + +def utc_now() -> datetime: + return datetime.now(timezone.utc) + + +class MonitorState(str, Enum): + unknown = "unknown" + up = "up" + down = "down" + + +class MonitorCreate(BaseModel): + name: str = Field(min_length=1, max_length=120) + url: HttpUrl + + +class MonitorUpdate(BaseModel): + name: str | None = Field(default=None, min_length=1, max_length=120) + url: HttpUrl | None = None + + @model_validator(mode="after") + def reject_nulls(self) -> "MonitorUpdate": + if any(value is None for value in self.model_dump(exclude_unset=True).values()): + raise ValueError("updated fields cannot be null") + return self + + +class CurrentStatus(BaseModel): + model_config = ConfigDict(frozen=True) + + state: MonitorState = MonitorState.unknown + checked_at: datetime | None = None + latency_ms: float | None = None + http_status: int | None = None + error: str | None = None + + +class Monitor(BaseModel): + model_config = ConfigDict(frozen=True) + + id: UUID + name: str + url: HttpUrl + created_at: datetime + updated_at: datetime + status: CurrentStatus + + +class CheckResult(BaseModel): + monitor_id: UUID + url: str + status: CurrentStatus