From d31ef63b2a21a3bf1b8ea2c1d6e7e63166e455e8 Mon Sep 17 00:00:00 2001 From: demo-bot Date: Sun, 9 Aug 2026 15:46:42 +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. --- app/models.py | 51 +++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/app/models.py b/app/models.py index 598882e..52e14d7 100644 --- a/app/models.py +++ b/app/models.py @@ -2,69 +2,40 @@ from datetime import UTC, datetime from enum import StrEnum from uuid import UUID, uuid4 -from pydantic import BaseModel, ConfigDict, Field, HttpUrl, model_validator - - -def now_utc() -> datetime: - return datetime.now(UTC) +from pydantic import AnyHttpUrl, BaseModel, ConfigDict, Field class State(StrEnum): - NEVER_CHECKED = "never_checked" + UNKNOWN = "unknown" UP = "up" DOWN = "down" ERROR = "error" - BLOCKED = "blocked" class MonitorCreate(BaseModel): name: str = Field(min_length=1, max_length=100) - url: HttpUrl - expected_status: int = Field(default=200, ge=100, le=599) + url: AnyHttpUrl class MonitorUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=100) - url: HttpUrl | None = None - expected_status: int | None = Field(default=None, ge=100, le=599) - - @model_validator(mode="after") - def not_empty(self) -> "MonitorUpdate": - if not self.model_fields_set: - raise ValueError("at least one field is required") - return self + url: AnyHttpUrl | None = None class CurrentStatus(BaseModel): - model_config = ConfigDict(frozen=True) - - state: State = State.NEVER_CHECKED + state: State = State.UNKNOWN checked_at: datetime | None = None - observed_status: int | None = None - latency_ms: float | None = None + status_code: int | None = None + latency_ms: float | None = Field(default=None, ge=0) error: str | None = None class Monitor(BaseModel): - model_config = ConfigDict(frozen=True) + model_config = ConfigDict(from_attributes=True) id: UUID = Field(default_factory=uuid4) name: str - url: HttpUrl - expected_status: int - created_at: datetime = Field(default_factory=now_utc) - updated_at: datetime = Field(default_factory=now_utc) + url: AnyHttpUrl + created_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) + updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC)) current_status: CurrentStatus = Field(default_factory=CurrentStatus) - - -class CheckResult(CurrentStatus): - monitor_id: UUID - - -class ErrorBody(BaseModel): - code: str - message: str - - -class ErrorResponse(BaseModel): - error: ErrorBody