fix: queue issue
This commit is contained in:
@@ -728,11 +728,11 @@ Every poster check action is logged:
|
||||
|
||||
### 8.1 Custom NFO Templates
|
||||
|
||||
You can customize NFO generation by modifying the NFO service:
|
||||
You can customise NFO generation by modifying `src/server/nfo/nfo_generator.py`:
|
||||
|
||||
```python
|
||||
# src/core/services/nfo_creator.py
|
||||
def generate_tvshow_nfo(self, metadata: dict) -> str:
|
||||
# src/server/nfo/nfo_generator.py
|
||||
def generate_tvshow_nfo(metadata: TVShowNFO) -> str:
|
||||
# Add custom fields or modify structure
|
||||
pass
|
||||
```
|
||||
@@ -811,78 +811,64 @@ updated via `create_tvshow_nfo()` / `update_tvshow_nfo()`.
|
||||
| `watched` | Always `false` on creation | ✅ |
|
||||
| `dateadded` | System clock at creation time (`YYYY-MM-DD HH:MM:SS`) | ✅ |
|
||||
|
||||
The mapping logic lives in `src/core/utils/nfo_mapper.py` (`tmdb_to_nfo_model`).
|
||||
The XML serialisation lives in `src/core/utils/nfo_generator.py`
|
||||
The mapping logic lives in `src/server/nfo/nfo_mapper.py` (`tmdb_to_nfo_model`).
|
||||
The XML serialisation lives in `src/server/nfo/nfo_generator.py`
|
||||
(`generate_tvshow_nfo`).
|
||||
|
||||
---
|
||||
|
||||
## 11. Automatic NFO Repair
|
||||
|
||||
NFO repair now runs as part of the scheduled daily folder scan rather than on every
|
||||
startup. When the scheduler triggers `FolderScanService.run_folder_scan()`, the first
|
||||
step is `perform_nfo_repair_scan(background_loader=None)`. Each incomplete NFO is
|
||||
queued as a background `asyncio` task, so the scan returns quickly while repairs
|
||||
continue asynchronously.
|
||||
NFO repair runs as part of the scheduled daily scan via ``SchedulerService``.
|
||||
When the scheduler fires, it calls ``_run_nfo_scan()`` which delegates to
|
||||
``NfoScanService.scan_all()``. This detects series whose ``tvshow.nfo`` is
|
||||
missing required tags and regenerates them from TMDB.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Scan** — `perform_nfo_repair_scan()` in
|
||||
`src/server/services/initialization_service.py` is called from
|
||||
`FolderScanService.run_folder_scan()` (`src/server/services/folder_scan_service.py`).
|
||||
2. **Detect** — `nfo_needs_repair(nfo_path)` from
|
||||
`src/core/services/nfo_repair_service.py` parses each `tvshow.nfo` with
|
||||
`lxml` and checks for the 13 required tags listed below.
|
||||
3. **Repair** — Series whose NFO is incomplete are queued for background reload
|
||||
via `asyncio.create_task`. Each task creates its own isolated
|
||||
:class:`NFOService` / :class:`TMDBClient` so concurrent tasks never share an
|
||||
``aiohttp`` session — this prevents "Connector is closed" errors when many repairs
|
||||
run in parallel. A semaphore caps TMDB concurrency at 3 to stay within rate limits.
|
||||
1. **Scheduler** fires the daily job (``SchedulerService._run_nfo_scan()``)
|
||||
2. **Detect** — ``NfoScanService._scan_series()`` parses each ``tvshow.nfo``
|
||||
and calls ``_create_nfo()`` / ``_update_nfo_if_needed()`` /
|
||||
``_regenerate_nfo()`` to fill missing tags from TMDB
|
||||
3. **Repair** — If TMDB lookup succeeds, the NFO is overwritten with complete
|
||||
data; if it fails, the original is kept and the failure is logged
|
||||
|
||||
### Tags Checked (13 required)
|
||||
### Tags Written / Updated
|
||||
|
||||
| XPath | Tag name |
|
||||
| ----------------- | --------------- |
|
||||
| `./title` | `title` |
|
||||
| `./originaltitle` | `originaltitle` |
|
||||
| `./year` | `year` |
|
||||
| `./plot` | `plot` |
|
||||
| `./runtime` | `runtime` |
|
||||
| `./premiered` | `premiered` |
|
||||
| `./status` | `status` |
|
||||
| `./imdbid` | `imdbid` |
|
||||
| `./genre` | `genre` |
|
||||
| `./studio` | `studio` |
|
||||
| `./country` | `country` |
|
||||
| `./actor/name` | `actor/name` |
|
||||
| `./watched` | `watched` |
|
||||
The NFO scan writes all 17 tags listed in the
|
||||
[Tag Reference](#10-tag-reference) above. Missing or empty tags trigger a
|
||||
regeneration from TMDB.
|
||||
|
||||
### Log Messages
|
||||
|
||||
| Message | Meaning |
|
||||
| ----------------------------------------------------------- | ------------------------------------------------- |
|
||||
| `NFO repair scan complete: 0 of N series queued for repair` | All NFOs are complete — no action needed |
|
||||
| `NFO repair scan complete: X of N series queued for repair` | X series had incomplete NFOs and have been queued |
|
||||
| `NFO repair scan skipped: TMDB API key not configured` | Set `tmdb_api_key` in `data/config.json` |
|
||||
| `NFO repair scan skipped: anime directory not configured` | Set `anime_directory` in `data/config.json` |
|
||||
|| Message | Meaning |
|
||||
| --- | --- |
|
||||
| `NFO scan complete: N series processed` | Scan finished normally |
|
||||
| `NFO scan skipped: TMDB API key not configured` | ``tmdb_api_key`` is empty — set it in ``data/config.json`` |
|
||||
| `NFO scan skipped: anime directory not configured` | ``anime_directory`` is not set |
|
||||
|
||||
### Triggering a Manual Repair
|
||||
### Manual Repair
|
||||
|
||||
You can also repair a single series on demand via the API:
|
||||
You can repair a single series on demand via the API:
|
||||
|
||||
```http
|
||||
POST /api/nfo/update/{series_key}
|
||||
POST /api/nfo/{series_key}/create
|
||||
```
|
||||
|
||||
This calls `NFOService.update_tvshow_nfo()` directly and overwrites the existing
|
||||
`tvshow.nfo` with fresh data from TMDB.
|
||||
or update with fresh TMDB data:
|
||||
|
||||
```http
|
||||
POST /api/nfo/{series_key}/update
|
||||
```
|
||||
|
||||
### Source Files
|
||||
|
||||
| File | Purpose |
|
||||
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `src/core/services/nfo_repair_service.py` | `REQUIRED_TAGS`, `parse_nfo_tags`, `find_missing_tags`, `nfo_needs_repair`, `NfoRepairService` |
|
||||
| `src/server/services/folder_scan_service.py` | `perform_nfo_repair_scan` — invoked during the scheduled daily folder scan |
|
||||
|| File | Purpose |
|
||||
| --- | --- |
|
||||
| ``src/server/services/scheduler/scheduler_service.py`` | ``SchedulerService._run_nfo_scan()`` — entry point called by the scheduler |
|
||||
| ``src/server/services/nfo_scan_service.py`` | ``NfoScanService.scan_all()`` — detects incomplete NFOs and regenerates them |
|
||||
| ``src/server/services/scan_service.py`` | ``ScanService`` — library rescan (episodes, missing files) |
|
||||
| ``src/server/services/folder_naming_service.py`` | ``FolderNamingService`` — renames folders to ``Title (YYYY)`` format |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user