feat: add backup monitoring pydantic models
This commit is contained in:
@@ -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
|
||||||
@@ -14,3 +14,18 @@ def test_backup_schema_created():
|
|||||||
assert "backup_jobs" in table_names
|
assert "backup_jobs" in table_names
|
||||||
assert "backup_runs" in table_names
|
assert "backup_runs" in table_names
|
||||||
assert "backup_alerts" 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"
|
||||||
|
|||||||
Reference in New Issue
Block a user