feat: implement WebSocket real-time progress updates
- Add ProgressService for centralized progress tracking and broadcasting - Integrate ProgressService with DownloadService for download progress - Integrate ProgressService with AnimeService for scan progress - Add progress-related WebSocket message models (ScanProgress, ErrorNotification, etc.) - Initialize ProgressService with WebSocket callback in application startup - Add comprehensive unit tests for ProgressService - Update infrastructure.md with ProgressService documentation - Remove completed WebSocket Real-time Updates task from instructions.md The ProgressService provides: - Real-time progress tracking for downloads, scans, and queue operations - Automatic progress percentage calculation - Progress lifecycle management (start, update, complete, fail, cancel) - WebSocket integration for instant client updates - Progress history with size limits - Thread-safe operations using asyncio locks - Support for metadata and custom messages Benefits: - Decoupled progress tracking from WebSocket broadcasting - Single reusable service across all components - Supports multiple concurrent operations efficiently - Centralized progress tracking simplifies monitoring - Instant feedback to users on long-running operations
This commit is contained in:
@@ -30,6 +30,11 @@ class WebSocketMessageType(str, Enum):
|
||||
QUEUE_PAUSED = "queue_paused"
|
||||
QUEUE_RESUMED = "queue_resumed"
|
||||
|
||||
# Progress-related messages
|
||||
SCAN_PROGRESS = "scan_progress"
|
||||
SCAN_COMPLETE = "scan_complete"
|
||||
SCAN_FAILED = "scan_failed"
|
||||
|
||||
# System messages
|
||||
SYSTEM_INFO = "system_info"
|
||||
SYSTEM_WARNING = "system_warning"
|
||||
@@ -188,3 +193,93 @@ class RoomSubscriptionRequest(BaseModel):
|
||||
room: str = Field(
|
||||
..., min_length=1, description="Room name to join or leave"
|
||||
)
|
||||
|
||||
|
||||
class ScanProgressMessage(BaseModel):
|
||||
"""Scan progress update message."""
|
||||
|
||||
type: WebSocketMessageType = Field(
|
||||
default=WebSocketMessageType.SCAN_PROGRESS,
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
...,
|
||||
description="Scan progress data including current, total, percent",
|
||||
)
|
||||
|
||||
|
||||
class ScanCompleteMessage(BaseModel):
|
||||
"""Scan completion message."""
|
||||
|
||||
type: WebSocketMessageType = Field(
|
||||
default=WebSocketMessageType.SCAN_COMPLETE,
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
...,
|
||||
description="Scan completion data including series_found, duration",
|
||||
)
|
||||
|
||||
|
||||
class ScanFailedMessage(BaseModel):
|
||||
"""Scan failure message."""
|
||||
|
||||
type: WebSocketMessageType = Field(
|
||||
default=WebSocketMessageType.SCAN_FAILED,
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
..., description="Scan error data including error_message"
|
||||
)
|
||||
|
||||
|
||||
class ErrorNotificationMessage(BaseModel):
|
||||
"""Error notification message for critical errors."""
|
||||
|
||||
type: WebSocketMessageType = Field(
|
||||
default=WebSocketMessageType.SYSTEM_ERROR,
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
...,
|
||||
description=(
|
||||
"Error notification data including severity, message, details"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class ProgressUpdateMessage(BaseModel):
|
||||
"""Generic progress update message.
|
||||
|
||||
Can be used for any type of progress (download, scan, queue, etc.)
|
||||
"""
|
||||
|
||||
type: WebSocketMessageType = Field(
|
||||
..., description="Type of progress message"
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
...,
|
||||
description=(
|
||||
"Progress data including id, status, percent, current, total"
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user