Fix download service init when anime dir not configured

This commit is contained in:
Lukas 2025-12-02 17:36:41 +01:00
parent 3b516c0e24
commit 7c56c8bef2
10 changed files with 57 additions and 160 deletions

View File

@ -17,7 +17,7 @@
"keep_days": 30 "keep_days": 30
}, },
"other": { "other": {
"master_password_hash": "$pbkdf2-sha256$29000$4Ny7tzZGaG2ttVaKsRZiLA$29mSesYMcIC0u0JfpP3SM7c.fEiE82.VYh9q2vZEBRw" "master_password_hash": "$pbkdf2-sha256$29000$R0hpDWEspRSidA4BoPTemw$NL4pP6ch.3sRxe6gjQ1tM3VPntwZMoZUFAI9sTQuHPE"
}, },
"version": "1.0.0" "version": "1.0.0"
} }

View File

@ -1,23 +0,0 @@
{
"name": "Aniworld",
"data_dir": "data",
"scheduler": {
"enabled": true,
"interval_minutes": 60
},
"logging": {
"level": "INFO",
"file": null,
"max_bytes": null,
"backup_count": 3
},
"backup": {
"enabled": false,
"path": "data/backups",
"keep_days": 30
},
"other": {
"master_password_hash": "$pbkdf2-sha256$29000$EUKI8d67d86ZE.K8VypF6A$4mqRLeh3WL2AsHFXNET.1D9T.weMNIE5Ffw6cIgA4ho"
},
"version": "1.0.0"
}

View File

@ -1,23 +0,0 @@
{
"name": "Aniworld",
"data_dir": "data",
"scheduler": {
"enabled": true,
"interval_minutes": 60
},
"logging": {
"level": "INFO",
"file": null,
"max_bytes": null,
"backup_count": 3
},
"backup": {
"enabled": false,
"path": "data/backups",
"keep_days": 30
},
"other": {
"master_password_hash": "$pbkdf2-sha256$29000$VooRQui9t/beGwMAgNAaQw$idnI9fpdgl0hAd7susBuX6rpux/L/k4PJ1QMQfjwpvo"
},
"version": "1.0.0"
}

View File

@ -1,23 +0,0 @@
{
"name": "Aniworld",
"data_dir": "data",
"scheduler": {
"enabled": true,
"interval_minutes": 60
},
"logging": {
"level": "INFO",
"file": null,
"max_bytes": null,
"backup_count": 3
},
"backup": {
"enabled": false,
"path": "data/backups",
"keep_days": 30
},
"other": {
"master_password_hash": "$pbkdf2-sha256$29000$/x8jxFgLofQegzAm5DzHeA$kO44/L.4b3sEDOCuzJkunefAZ9ap5jsFZP/JDaRIUt0"
},
"version": "1.0.0"
}

View File

@ -1,23 +0,0 @@
{
"name": "Aniworld",
"data_dir": "data",
"scheduler": {
"enabled": true,
"interval_minutes": 60
},
"logging": {
"level": "INFO",
"file": null,
"max_bytes": null,
"backup_count": 3
},
"backup": {
"enabled": false,
"path": "data/backups",
"keep_days": 30
},
"other": {
"master_password_hash": "$pbkdf2-sha256$29000$htA6x1jrHYPwvre2FkJoTQ$37rrE4hOMgdowfzS9XaaH/EjPDZZFSlc0RL1blcXEVU"
},
"version": "1.0.0"
}

View File

@ -1,23 +0,0 @@
{
"name": "Aniworld",
"data_dir": "data",
"scheduler": {
"enabled": true,
"interval_minutes": 60
},
"logging": {
"level": "INFO",
"file": null,
"max_bytes": null,
"backup_count": 3
},
"backup": {
"enabled": false,
"path": "data/backups",
"keep_days": 30
},
"other": {
"master_password_hash": "$pbkdf2-sha256$29000$.t.bk1IKQah1bg0BoNS6tw$TbbOVxdX4U7xhiRPPyJM6cXl5EnVzlM/3YMZF714Aoc"
},
"version": "1.0.0"
}

View File

@ -17,7 +17,7 @@
"keep_days": 30 "keep_days": 30
}, },
"other": { "other": {
"master_password_hash": "$pbkdf2-sha256$29000$F0JIKQWAEEJoba3VGuOckw$ae64QkQc0QkMiSiO3H3Bg8mZE5nOQ8hrN5gl9LQLjnw" "master_password_hash": "$pbkdf2-sha256$29000$JWTsXWstZYyxNiYEQAihFA$K9QPNr2J9biZEX/7SFKU94dnynvyCICrGjKtZcEu6t8"
}, },
"version": "1.0.0" "version": "1.0.0"
} }

View File

@ -166,22 +166,22 @@ All series-related WebSocket events include `key` as the primary identifier in t
### DownloadQueueItem Fields ### DownloadQueueItem Fields
| Field | Type | Purpose | | Field | Type | Purpose |
| -------------- | ----------- | --------------------------------------------- | | -------------- | ----------- | ----------------------------------------- |
| `id` | String (PK) | UUID for the queue item | | `id` | String (PK) | UUID for the queue item |
| `serie_id` | String | Series key for identification | | `serie_id` | String | Series key for identification |
| `serie_folder` | String | Filesystem folder path | | `serie_folder` | String | Filesystem folder path |
| `serie_name` | String | Display name for the series | | `serie_name` | String | Display name for the series |
| `season` | Integer | Season number | | `season` | Integer | Season number |
| `episode` | Integer | Episode number | | `episode` | Integer | Episode number |
| `status` | Enum | pending, downloading, completed, failed | | `status` | Enum | pending, downloading, completed, failed |
| `priority` | Enum | low, normal, high | | `priority` | Enum | low, normal, high |
| `progress` | Float | Download progress percentage (0.0-100.0) | | `progress` | Float | Download progress percentage (0.0-100.0) |
| `error` | String | Error message if failed | | `error` | String | Error message if failed |
| `retry_count` | Integer | Number of retry attempts | | `retry_count` | Integer | Number of retry attempts |
| `added_at` | DateTime | When item was added to queue | | `added_at` | DateTime | When item was added to queue |
| `started_at` | DateTime | When download started (nullable) | | `started_at` | DateTime | When download started (nullable) |
| `completed_at` | DateTime | When download completed/failed (nullable) | | `completed_at` | DateTime | When download completed/failed (nullable) |
## Data Storage ## Data Storage
@ -189,13 +189,13 @@ All series-related WebSocket events include `key` as the primary identifier in t
The application uses **SQLite database** as the primary storage for all application data. The application uses **SQLite database** as the primary storage for all application data.
| Data Type | Storage Location | Service | | Data Type | Storage Location | Service |
| --------------- | ------------------ | ---------------------------- | | -------------- | ------------------ | --------------------------------------- |
| Anime Series | `data/aniworld.db` | `AnimeSeriesService` | | Anime Series | `data/aniworld.db` | `AnimeSeriesService` |
| Episodes | `data/aniworld.db` | `AnimeSeriesService` | | Episodes | `data/aniworld.db` | `AnimeSeriesService` |
| Download Queue | `data/aniworld.db` | `DownloadService` via `QueueRepository` | | Download Queue | `data/aniworld.db` | `DownloadService` via `QueueRepository` |
| User Sessions | `data/aniworld.db` | `AuthService` | | User Sessions | `data/aniworld.db` | `AuthService` |
| Configuration | `data/config.json` | `ConfigService` | | Configuration | `data/config.json` | `ConfigService` |
### Download Queue Storage ### Download Queue Storage
@ -219,11 +219,12 @@ await repository.update_progress(item_id, progress=45.5, downloaded=450, total=1
``` ```
**Queue Persistence Features:** **Queue Persistence Features:**
- Queue state survives server restarts
- Items in `downloading` status are reset to `pending` on startup - Queue state survives server restarts
- Failed items within retry limit are automatically re-queued - Items in `downloading` status are reset to `pending` on startup
- Completed and failed history is preserved (with limits) - Failed items within retry limit are automatically re-queued
- Real-time progress updates are persisted to database - Completed and failed history is preserved (with limits)
- Real-time progress updates are persisted to database
### Anime Series Database Storage ### Anime Series Database Storage

View File

@ -125,20 +125,21 @@ For each task completed:
The download queue has been successfully migrated from JSON file to SQLite database: The download queue has been successfully migrated from JSON file to SQLite database:
| Component | Status | Description | | Component | Status | Description |
| ---------------------- | --------- | ------------------------------------------------ | | --------------------- | ------- | ------------------------------------------------- |
| QueueRepository | ✅ Done | `src/server/services/queue_repository.py` | | QueueRepository | ✅ Done | `src/server/services/queue_repository.py` |
| DownloadService | ✅ Done | Refactored to use repository pattern | | DownloadService | ✅ Done | Refactored to use repository pattern |
| Application Startup | ✅ Done | Queue restored from database on startup | | Application Startup | ✅ Done | Queue restored from database on startup |
| API Endpoints | ✅ Done | All endpoints work with database-backed queue | | API Endpoints | ✅ Done | All endpoints work with database-backed queue |
| Tests Updated | ✅ Done | All 1104 tests passing with MockQueueRepository | | Tests Updated | ✅ Done | All 1104 tests passing with MockQueueRepository |
| Documentation Updated | ✅ Done | `infrastructure.md` updated with new architecture| | Documentation Updated | ✅ Done | `infrastructure.md` updated with new architecture |
**Key Changes:** **Key Changes:**
- `DownloadService` no longer uses `persistence_path` parameter
- Queue state is persisted to SQLite via `QueueRepository` - `DownloadService` no longer uses `persistence_path` parameter
- In-memory cache maintained for performance - Queue state is persisted to SQLite via `QueueRepository`
- All tests use `MockQueueRepository` fixture - In-memory cache maintained for performance
- All tests use `MockQueueRepository` fixture
--- ---

View File

@ -113,11 +113,21 @@ async def lifespan(app: FastAPI):
progress_service.subscribe("progress_updated", progress_event_handler) progress_service.subscribe("progress_updated", progress_event_handler)
# Initialize download service and restore queue from database # Initialize download service and restore queue from database
# Only if anime directory is configured
try: try:
from src.server.config.settings import settings
from src.server.utils.dependencies import get_download_service from src.server.utils.dependencies import get_download_service
download_service = get_download_service()
await download_service.initialize() if settings.anime_directory:
logger.info("Download service initialized and queue restored") download_service = get_download_service()
await download_service.initialize()
logger.info("Download service initialized and queue restored")
else:
logger.info(
"Download service initialization skipped - "
"anime directory not configured"
)
except Exception as e: except Exception as e:
logger.warning("Failed to initialize download service: %s", e) logger.warning("Failed to initialize download service: %s", e)
# Continue startup - download service can be initialized later # Continue startup - download service can be initialized later