From bd9765d4d9600f90bf48f31670476f8f3e077ab0 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Mon, 11 May 2026 20:27:28 +0200 Subject: [PATCH] feat: add backup monitoring pydantic models --- .../models/backups.py | 65 +++++++++++++++++++ backend/tests/test_backups.py | 15 +++++ 2 files changed, 80 insertions(+) create mode 100644 backend/src/media_library_viewer_api/models/backups.py diff --git a/backend/src/media_library_viewer_api/models/backups.py b/backend/src/media_library_viewer_api/models/backups.py new file mode 100644 index 0000000..8b4cba7 --- /dev/null +++ b/backend/src/media_library_viewer_api/models/backups.py @@ -0,0 +1,65 @@ +from datetime import datetime +from typing import Any +from pydantic import BaseModel, Field, field_validator + + +class BackupReportRequest(BaseModel): + name: str = Field(..., min_length=1) + source: str | None = None + target: str | None = None + schedule_interval_seconds: int | None = Field(None, gt=0) + started_at: datetime + ended_at: datetime | None = None + status: str = Field(..., pattern="^(success|failure|in_progress)$") + bytes_transferred: int | None = Field(None, ge=0) + duration_ms: int | None = None + error_message: str | None = None + details: dict[str, Any] | None = None + + @field_validator("ended_at", "duration_ms") + @classmethod + def validate_success_fields(cls, v, info): + if info.data.get("status") == "success" and v is None: + raise ValueError(f"{info.field_name} is required when status is 'success'") + return v + + +class BackupJobResponse(BaseModel): + id: str + name: str + source: str | None + target: str | None + schedule_interval_seconds: int | None + created_at: int + + +class BackupRunResponse(BaseModel): + id: str + job_id: str + started_at: int + ended_at: int | None + status: str + bytes_transferred: int | None + duration_ms: int | None + error_message: str | None + details_json: dict[str, Any] | None + created_at: int + + +class BackupAlertResponse(BaseModel): + id: str + job_id: str + run_id: str | None + alert_type: str + severity: str + message: str + acknowledged: bool + resolved_at: int | None + created_at: int + + +class BackupDashboardSummary(BaseModel): + total_jobs: int + success_rate_24h: float + active_alerts: int + last_failed_at: int | None diff --git a/backend/tests/test_backups.py b/backend/tests/test_backups.py index 7ba9fb8..bfdae86 100644 --- a/backend/tests/test_backups.py +++ b/backend/tests/test_backups.py @@ -14,3 +14,18 @@ def test_backup_schema_created(): assert "backup_jobs" in table_names assert "backup_runs" in table_names assert "backup_alerts" in table_names + + +def test_backup_report_model(): + from media_library_viewer_api.models.backups import BackupReportRequest + + report = BackupReportRequest( + name="test-backup", + started_at="2026-05-11T02:00:00Z", + status="success", + ended_at="2026-05-11T02:15:00Z", + duration_ms=900000, + bytes_transferred=1024, + ) + assert report.name == "test-backup" + assert report.status == "success"