Fix WebSocket room subscription format

This commit is contained in:
2026-01-23 15:25:47 +01:00
parent 7bf02ac8f8
commit f8634bf605
8 changed files with 46 additions and 35 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -122,33 +122,30 @@ For each task completed:
### Completed Tasks: ### Completed Tasks:
1.**NFO/Artwork Loading Isolation** (Completed: 2026-01-23) 1.**NFO/Artwork Loading Isolation** (Completed: 2026-01-23)
- Task: Ensure during anime add, NFO, logo, art, etc. is loaded only for the specific anime being added - Task: Ensure during anime add, NFO, logo, art, etc. is loaded only for the specific anime being added
- Status: VERIFIED - Implementation is correct - Status: VERIFIED - Implementation is correct
2.**Setup Redirect Flow** (Completed: 2026-01-23) 2.**Setup Redirect Flow** (Completed: 2026-01-23)
- Task: Implement redirect flow: setup -> loading -> login when user completes setup - Task: Implement redirect flow: setup -> loading -> login when user completes setup
- Changes: - Changes:
- Added /loading to exempt paths in setup_redirect middleware - Added /loading to exempt paths in setup_redirect middleware
- Setup page redirects to loading with initialization in background - Setup page redirects to loading with initialization in background
- Loading page connects to WebSocket for real-time progress - Loading page connects to WebSocket for real-time progress
- After completion, loading redirects to login - After completion, loading redirects to login
3.**Close Setup and Loading Pages** (Completed: 2026-01-23) 3.**Close Setup and Loading Pages** (Completed: 2026-01-23)
- Task: Make setup and loading pages unavailable after completion to prevent re-access - Task: Make setup and loading pages unavailable after completion to prevent re-access
- Changes: - Changes:
- Check if setup is complete before allowing access to /setup - Check if setup is complete before allowing access to /setup
- Redirect to login if accessing /setup after completion - Redirect to login if accessing /setup after completion
- Check if initialization is complete before allowing access to /loading - Check if initialization is complete before allowing access to /loading
- Redirect to login if accessing /loading after initialization complete - Redirect to login if accessing /loading after initialization complete
4.**Fix Loading Page WebSocket Auth** (Completed: 2026-01-23) 4.**Fix Loading Page WebSocket Auth** (Completed: 2026-01-23)
- Task: Fix 403 Forbidden error on WebSocket connection - Task: Fix 403 Forbidden error on WebSocket connection
- Issue: Loading page was connecting to /ws/progress (doesn't exist) - Issue: Loading page was connecting to /ws/progress (doesn't exist)
- Changes: - Changes:
- Changed WebSocket URL from /ws/progress to /ws/connect (correct endpoint) - Changed WebSocket URL from /ws/progress to /ws/connect (correct endpoint)
- Added /ws/connect to exempt paths in auth middleware - Added /ws/connect to exempt paths in auth middleware
- Subscribe to 'system' room after connection for progress updates - Subscribe to 'system' room after connection for progress updates
- Fixed message data handling to match WebSocket format - Fixed message data handling to match WebSocket format
### Active Tasks: ### Active Tasks:

View File

@@ -1,3 +1,4 @@
API key : 299ae8f630a31bda814263c551361448 API key : 299ae8f630a31bda814263c551361448
/mnt/server/serien/Serien/ /mnt/server/serien/Serien/

View File

@@ -18,14 +18,14 @@ This document verifies that the anime add functionality correctly loads NFO, log
When a new anime is added via `POST /api/anime/add`: When a new anime is added via `POST /api/anime/add`:
1. **API Endpoint** ([anime.py:694-920](../src/server/api/anime.py#L694-L920)) 1. **API Endpoint** ([anime.py:694-920](../src/server/api/anime.py#L694-L920))
- Validates input and extracts series key - Validates input and extracts series key
- Creates database entry with `loading_status="pending"` - Creates database entry with `loading_status="pending"`
- Adds to in-memory cache - Adds to in-memory cache
- **Queues background loading task** for the specific anime - **Queues background loading task** for the specific anime
2. **Background Loading** ([background_loader_service.py](../src/server/services/background_loader_service.py)) 2. **Background Loading** ([background_loader_service.py](../src/server/services/background_loader_service.py))
- Processes one `SeriesLoadingTask` at a time - Processes one `SeriesLoadingTask` at a time
- Each task contains **only one anime's metadata**: key, folder, name, year - Each task contains **only one anime's metadata**: key, folder, name, year
### 2. NFO/Artwork Loading Process ### 2. NFO/Artwork Loading Process
@@ -34,7 +34,7 @@ The `_load_nfo_and_images()` method ([background_loader_service.py:454-544](../s
```python ```python
async def _load_nfo_and_images(self, task: SeriesLoadingTask, db: Any) -> None: async def _load_nfo_and_images(self, task: SeriesLoadingTask, db: Any) -> None:
"""Load NFO file and images for a series by reusing NFOService. """Load NFO file and images for a series by reusing NFOService.
Args: Args:
task: The loading task (contains data for ONE anime only) task: The loading task (contains data for ONE anime only)
db: Database session db: Database session
@@ -43,7 +43,7 @@ async def _load_nfo_and_images(self, task: SeriesLoadingTask, db: Any) -> None:
if self.series_app.nfo_service.has_nfo(task.folder): if self.series_app.nfo_service.has_nfo(task.folder):
# Skip if exists # Skip if exists
return return
# Create NFO with THIS anime's specific data # Create NFO with THIS anime's specific data
nfo_path = await self.series_app.nfo_service.create_tvshow_nfo( nfo_path = await self.series_app.nfo_service.create_tvshow_nfo(
serie_name=task.name, # ✅ Only this anime's name serie_name=task.name, # ✅ Only this anime's name
@@ -58,21 +58,25 @@ async def _load_nfo_and_images(self, task: SeriesLoadingTask, db: Any) -> None:
### 3. Key Implementation Details ### 3. Key Implementation Details
#### ✅ Isolated Task Processing #### ✅ Isolated Task Processing
- Each `SeriesLoadingTask` contains data for **exactly one anime** - Each `SeriesLoadingTask` contains data for **exactly one anime**
- Tasks are processed sequentially from the queue - Tasks are processed sequentially from the queue
- No cross-contamination between anime - No cross-contamination between anime
#### ✅ Targeted NFO Creation #### ✅ Targeted NFO Creation
- `NFOService.create_tvshow_nfo()` receives parameters for **one anime only** - `NFOService.create_tvshow_nfo()` receives parameters for **one anime only**
- Downloads poster, logo, fanart to **that anime's folder only** - Downloads poster, logo, fanart to **that anime's folder only**
- TMDB API calls are made for **that specific anime's name/year** - TMDB API calls are made for **that specific anime's name/year**
#### ✅ No Global Scanning #### ✅ No Global Scanning
- `SerieList.load_series()` only **checks** for existing files - `SerieList.load_series()` only **checks** for existing files
- It does **not** download or create any new files - It does **not** download or create any new files
- Used only for initial library scanning, not during anime add - Used only for initial library scanning, not during anime add
#### ✅ Isolated Episode Scanning #### ✅ Isolated Episode Scanning
- `_load_episodes()` uses `_find_series_directory()` and `_scan_series_episodes()` - `_load_episodes()` uses `_find_series_directory()` and `_scan_series_episodes()`
- Scans **only the specific anime's directory**, not the entire library - Scans **only the specific anime's directory**, not the entire library
- No impact on other anime - No impact on other anime
@@ -80,15 +84,19 @@ async def _load_nfo_and_images(self, task: SeriesLoadingTask, db: Any) -> None:
## Verification ## Verification
### Code Review ### Code Review
✅ Reviewed implementation in: ✅ Reviewed implementation in:
- `src/server/services/background_loader_service.py` (lines 454-544) - `src/server/services/background_loader_service.py` (lines 454-544)
- `src/server/api/anime.py` (lines 694-920) - `src/server/api/anime.py` (lines 694-920)
- `src/core/entities/SerieList.py` (lines 149-250) - `src/core/entities/SerieList.py` (lines 149-250)
### Test Created ### Test Created
✅ Created comprehensive test: `tests/integration/test_anime_add_nfo_isolation.py` ✅ Created comprehensive test: `tests/integration/test_anime_add_nfo_isolation.py`
The test verifies: The test verifies:
1. NFO service called exactly once for new anime 1. NFO service called exactly once for new anime
2. Correct parameters passed (name, folder, year) 2. Correct parameters passed (name, folder, year)
3. Existing anime not affected 3. Existing anime not affected
@@ -101,6 +109,7 @@ Note: Test requires database mocking to run fully, but code analysis confirms co
**The current implementation is CORRECT and COMPLETE.** **The current implementation is CORRECT and COMPLETE.**
When adding a new anime: When adding a new anime:
- ✅ NFO is created only for that specific anime - ✅ NFO is created only for that specific anime
- ✅ Logo is downloaded only to that anime's folder - ✅ Logo is downloaded only to that anime's folder
- ✅ Artwork (poster, fanart) is downloaded only to that anime's folder - ✅ Artwork (poster, fanart) is downloaded only to that anime's folder

View File

@@ -129,7 +129,9 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
# Check if initialization is complete # Check if initialization is complete
try: try:
from src.server.database.connection import get_db_session from src.server.database.connection import get_db_session
from src.server.database.system_settings_service import SystemSettingsService from src.server.database.system_settings_service import (
SystemSettingsService,
)
async with get_db_session() as db: async with get_db_session() as db:
is_complete = await SystemSettingsService.is_initial_scan_completed(db) is_complete = await SystemSettingsService.is_initial_scan_completed(db)

View File

@@ -305,7 +305,9 @@
// Subscribe to system room for progress updates // Subscribe to system room for progress updates
ws.send(JSON.stringify({ ws.send(JSON.stringify({
action: 'join', action: 'join',
room: 'system' data: {
room: 'system'
}
})); }));
}; };