fix: queue issue
This commit is contained in:
@@ -80,9 +80,12 @@ src/server/
|
||||
| +-- progress_service.py # Progress tracking
|
||||
| +-- websocket_service.py# WebSocket broadcasting
|
||||
| +-- queue_repository.py # Database persistence
|
||||
| +-- nfo_service.py # NFO metadata management
|
||||
| +-- setup_service.py # Series key resolution from folder names
|
||||
| +-- folder_scan_service.py # Daily folder maintenance scan
|
||||
| +-- nfo_scan_service.py # NFO creation, update, and regeneration from TMDB
|
||||
| +-- scan_service.py # Library rescan (episodes, missing files)
|
||||
| +-- folder_naming_service.py # Folder rename to Title (YYYY) convention
|
||||
| +-- scheduler/ # Scheduled tasks
|
||||
| | +-- scheduler_service.py # Cron-based library rescans
|
||||
+-- models/ # Pydantic models
|
||||
| +-- auth.py # Auth request/response models
|
||||
| +-- config.py # Configuration models
|
||||
@@ -166,11 +169,42 @@ src/server/web/static/js/
|
||||
| +-- socket-handler.js # WebSocket event handlers
|
||||
| +-- app-init.js # Application initialization
|
||||
+-- queue/ # Queue page modules
|
||||
+-- queue-api.js # Queue API interactions
|
||||
+-- queue-renderer.js # Queue list rendering
|
||||
+-- progress-handler.js # Download progress updates
|
||||
+-- queue-socket-handler.js # WebSocket events for queue
|
||||
+-- queue-init.js # Queue page initialization
|
||||
| +-- queue-api.js # Queue API wrapper (uses ApiClient internally)
|
||||
| +-- queue-renderer.js # Queue DOM rendering
|
||||
| +-- progress-handler.js # Download progress updates
|
||||
| +-- queue-socket-handler.js # WebSocket events for queue
|
||||
| +-- queue-init.js # Queue page initialisation and orchestration
|
||||
```
|
||||
|
||||
**Queue Module Public APIs:**
|
||||
|
||||
```javascript
|
||||
// queue-api.js — wraps /api/queue/* endpoints via AniWorld.ApiClient
|
||||
AniWorld.QueueAPI.loadQueueData() // GET /api/queue/status → queue data
|
||||
AniWorld.QueueAPI.startQueue() // POST /api/queue/start
|
||||
AniWorld.QueueAPI.stopQueue() // POST /api/queue/stop
|
||||
AniWorld.QueueAPI.removeFromQueue(itemId) // DELETE /api/queue/{item_id}
|
||||
AniWorld.QueueAPI.retryDownloads(itemIds) // POST /api/queue/retry
|
||||
AniWorld.QueueAPI.clearCompleted() // DELETE /api/queue/completed
|
||||
AniWorld.QueueAPI.clearFailed() // DELETE /api/queue/failed
|
||||
AniWorld.QueueAPI.clearPending() // DELETE /api/queue/pending
|
||||
|
||||
// queue-init.js — page orchestration (imports QueueAPI internally)
|
||||
AniWorld.QueueApp.init() // Bootstrap; calls loadQueueData()
|
||||
AniWorld.QueueApp.loadQueueData() // Fetch queue data and render
|
||||
AniWorld.QueueApp.startDownload() // Start queue processing
|
||||
AniWorld.QueueApp.stopDownloads() // Stop queue processing
|
||||
AniWorld.QueueApp.removeFromQueue(id) // Remove single item
|
||||
AniWorld.QueueApp.retryDownload(id) // Retry failed item
|
||||
AniWorld.QueueApp.retryAllFailed() // Retry all failed items
|
||||
AniWorld.QueueApp.clearQueue(type) // Clear completed|failed|pending
|
||||
```
|
||||
|
||||
> **Module dependency rule**: Queue page modules must access API endpoints via
|
||||
> `AniWorld.QueueAPI.<method>()`. The `API` object (`AniWorld.Constants.API`) is
|
||||
> private to each module's IIFE closure and is NOT a global. Do NOT use bare
|
||||
> `fetch(API.QUEUE_STATUS, ...)` in `queue-init.js` — use
|
||||
> `AniWorld.QueueAPI.loadQueueData()` instead.
|
||||
```
|
||||
|
||||
#### Module Pattern
|
||||
@@ -195,51 +229,48 @@ AniWorld.ModuleName = (function () {
|
||||
|
||||
Source: [src/server/web/static/](../src/server/web/static/)
|
||||
|
||||
### 2.3 Core Layer (`src/core/`)
|
||||
### 2.3 Core Layer (`src/server/`)
|
||||
|
||||
Domain logic for anime series management.
|
||||
Domain logic for anime series management, NFO metadata, and episode downloads.
|
||||
|
||||
```
|
||||
src/core/
|
||||
+-- SeriesApp.py # Main application facade
|
||||
src/server/
|
||||
+-- SerieScanner.py # Directory scanning, targeted single-series scan
|
||||
+-- entities/ # Domain entities
|
||||
| +-- series.py # Serie class with sanitized_folder property
|
||||
| +-- SerieList.py # SerieList collection with sanitized folder support
|
||||
| +-- nfo_models.py # Pydantic models for tvshow.nfo (TVShowNFO, ActorInfo…)
|
||||
+-- services/ # Domain services
|
||||
| +-- nfo_service.py # NFO lifecycle: create / update tvshow.nfo
|
||||
| +-- nfo_repair_service.py # Detect & repair incomplete tvshow.nfo files
|
||||
| | # (parse_nfo_tags, find_missing_tags, NfoRepairService)
|
||||
| +-- tmdb_client.py # Async TMDB API client
|
||||
+-- utils/ # Utility helpers (no side-effects)
|
||||
| +-- nfo_generator.py # TVShowNFO → XML serialiser
|
||||
+-- SerieList.py # Series collection (stub; see src/server/database/SerieList.py)
|
||||
+-- nfo/ # NFO metadata generation and mapping
|
||||
| +-- nfo_generator.py # TVShowNFO → XML serialiser (generate_tvshow_nfo)
|
||||
| +-- nfo_mapper.py # TMDB API dict → TVShowNFO (tmdb_to_nfo_model,
|
||||
| | # _extract_rating_by_country, _extract_fsk_rating)
|
||||
| +-- image_downloader.py # TMDB image downloader
|
||||
| +-- nfo_models.py # Pydantic models for NFO XML (TVShowNFO, ActorInfo…)
|
||||
| +-- tmdb_client.py # Async TMDB API client
|
||||
+-- providers/ # External provider adapters
|
||||
| +-- base_provider.py # Loader interface
|
||||
| +-- provider_factory.py # Provider registry
|
||||
+-- interfaces/ # Abstract interfaces
|
||||
| +-- aniworld_provider.py # AniWorld scraper
|
||||
| +-- enhanced_provider.py # Multi-provider with failover
|
||||
| +-- provider_config.py # Provider preference configuration
|
||||
| +-- streaming/ # Provider-specific extractors (VOE, Doodstream, etc.)
|
||||
+-- entities/
|
||||
| +-- nfo_models.py # Domain entities for NFO (aligns with nfo/nfo_models.py)
|
||||
+-- interfaces/
|
||||
| +-- callbacks.py # Progress callback system
|
||||
+-- exceptions/ # Domain exceptions
|
||||
+-- Exceptions.py # Custom exceptions
|
||||
| +-- providers.py # Provider interface definitions
|
||||
+-- exceptions/
|
||||
+-- Exceptions.py # Custom exceptions
|
||||
```
|
||||
|
||||
**Key Components:**
|
||||
|
||||
| Component | Purpose |
|
||||
| -------------- | -------------------------------------------------------------------------- |
|
||||
| `SeriesApp` | Main application facade for anime operations |
|
||||
| `SerieScanner` | Scans directories for anime; `scan_single_series()` for targeted scans |
|
||||
| `Serie` | Domain entity with `sanitized_folder` property for filesystem-safe names |
|
||||
| `SerieList` | Collection management with automatic folder creation using sanitized names |
|
||||
|| Component | Purpose |
|
||||
| --- | --- |
|
||||
| `SerieScanner` | Scans directories for anime; `scan_single_series()` for targeted scans |
|
||||
| `tmdb_client.py` | Async TMDB API client |
|
||||
| `nfo_generator.py` | Serialises `TVShowNFO` to XML |
|
||||
| `nfo_mapper.py` | Maps TMDB API response to `TVShowNFO` domain model |
|
||||
| `enhanced_provider.py` | Multi-provider downloader with failover chain |
|
||||
|
||||
**Initialization:**
|
||||
|
||||
`SeriesApp` is initialized with `skip_load=True` passed to `SerieList`, preventing automatic loading of series from data files on every instantiation. Series data is loaded once during application setup via `sync_series_from_data_files()` in the FastAPI lifespan, which reads data files and syncs them to the database. Subsequent operations load series from the database through the service layer.
|
||||
|
||||
Source: [src/core/](../src/core/)
|
||||
> **Note:** The `src/core/` directory was an earlier architectural proposal and is
|
||||
> currently empty. All domain logic lives under `src/server/`.
|
||||
|
||||
### 2.4 Infrastructure Layer (`src/infrastructure/`)
|
||||
|
||||
@@ -428,8 +459,8 @@ Source: [src/server/middleware/auth.py](../src/server/middleware/auth.py#L1-L209
|
||||
| Exception / cancellation | Temp + `.part` fragments removed in `except` block |
|
||||
|
||||
Source: [src/server/services/download_service.py](../src/server/services/download_service.py#L1-L150),
|
||||
[src/core/providers/aniworld_provider.py](../src/core/providers/aniworld_provider.py),
|
||||
[src/core/providers/enhanced_provider.py](../src/core/providers/enhanced_provider.py)
|
||||
[src/server/providers/aniworld_provider.py](../src/server/providers/aniworld_provider.py),
|
||||
[src/server/providers/enhanced_provider.py](../src/server/providers/enhanced_provider.py)
|
||||
|
||||
### 3.3 WebSocket Event Flow
|
||||
|
||||
@@ -731,7 +762,7 @@ class Loader(ABC):
|
||||
def get_episodes(self, serie: Serie) -> Dict[int, List[int]]: ...
|
||||
```
|
||||
|
||||
Source: [src/core/providers/base_provider.py](../src/core/providers/base_provider.py)
|
||||
Source: [src/server/providers/base_provider.py](../src/server/providers/base_provider.py)
|
||||
|
||||
### 8.2 Filesystem Integration
|
||||
|
||||
@@ -745,7 +776,7 @@ SerieScanner(
|
||||
)
|
||||
```
|
||||
|
||||
Source: [src/core/SerieScanner.py](../src/core/SerieScanner.py#L59-L96)
|
||||
Source: [src/server/SerieScanner.py](../src/server/SerieScanner.py#L59-L96)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user