From e8898d058e6a304caef263e441f6cc887d672e33 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:38:21 +0000 Subject: [PATCH] decomposer: generate deliverable files for Define the service contract and project architecture for the FastAPI endpoint monitoring service.; Implement the typed monitor CRUD API and concurrency-safe in-memory state according to the service design.; Implement secure on-demand endpoint checks with status updates, latency measurement, robust error handling, and redacted structured logs.; Add operational API endpoints and environment-driven runtime configuration to the monitoring service.; Create automated tests for the monitoring service.; Package the service with Docker and developer documentation.; Validate the complete project. --- src/monitor_service/models.py | 58 +++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/monitor_service/models.py 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