some fixes
This commit is contained in:
parent
ae77a11782
commit
e0a7c6baa9
@ -170,10 +170,10 @@ All series-related WebSocket events include `key` as the primary identifier in t
|
|||||||
|
|
||||||
The application uses **SQLite database** as the primary storage for anime series metadata. This replaces the legacy file-based storage system.
|
The application uses **SQLite database** as the primary storage for anime series metadata. This replaces the legacy file-based storage system.
|
||||||
|
|
||||||
| Storage Method | Status | Location | Purpose |
|
| Storage Method | Status | Location | Purpose |
|
||||||
| -------------- | --------------------- | ------------------------- | ------------------------------ |
|
| -------------- | --------------------- | -------------------- | ----------------------------- |
|
||||||
| SQLite DB | **Primary (Current)** | `data/aniworld.db` | All series metadata and state |
|
| SQLite DB | **Primary (Current)** | `data/aniworld.db` | All series metadata and state |
|
||||||
| Data Files | **Deprecated** | `{anime_dir}/*/data` | Legacy per-series JSON files |
|
| Data Files | **Deprecated** | `{anime_dir}/*/data` | Legacy per-series JSON files |
|
||||||
|
|
||||||
### Database Storage (Recommended)
|
### Database Storage (Recommended)
|
||||||
|
|
||||||
@ -194,9 +194,9 @@ await AnimeSeriesService.update(db_session, series_id, update_data)
|
|||||||
|
|
||||||
The legacy file-based storage is **deprecated** and will be removed in v3.0.0:
|
The legacy file-based storage is **deprecated** and will be removed in v3.0.0:
|
||||||
|
|
||||||
- `Serie.save_to_file()` - Deprecated, use `AnimeSeriesService.create()`
|
- `Serie.save_to_file()` - Deprecated, use `AnimeSeriesService.create()`
|
||||||
- `Serie.load_from_file()` - Deprecated, use `AnimeSeriesService.get_by_key()`
|
- `Serie.load_from_file()` - Deprecated, use `AnimeSeriesService.get_by_key()`
|
||||||
- `SerieList.add()` - Deprecated, use `SerieList.add_to_db()`
|
- `SerieList.add()` - Deprecated, use `SerieList.add_to_db()`
|
||||||
|
|
||||||
Deprecation warnings are raised when using these methods.
|
Deprecation warnings are raised when using these methods.
|
||||||
|
|
||||||
|
|||||||
@ -288,9 +288,10 @@ async def lifespan(app: FastAPI):
|
|||||||
- Test duplicate key handling
|
- Test duplicate key handling
|
||||||
|
|
||||||
**Implementation Notes:**
|
**Implementation Notes:**
|
||||||
- Added `get_optional_database_session()` dependency in `dependencies.py` for graceful fallback
|
|
||||||
- Endpoint saves to database when available, falls back to file-based storage when not
|
- Added `get_optional_database_session()` dependency in `dependencies.py` for graceful fallback
|
||||||
- All 55 API tests and 809 unit tests pass
|
- Endpoint saves to database when available, falls back to file-based storage when not
|
||||||
|
- All 55 API tests and 809 unit tests pass
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -319,12 +320,13 @@ async def lifespan(app: FastAPI):
|
|||||||
- Test dependency injection provides correct sessions
|
- Test dependency injection provides correct sessions
|
||||||
|
|
||||||
**Implementation Notes:**
|
**Implementation Notes:**
|
||||||
- Added `db_session` parameter to `SeriesApp.__init__()`
|
|
||||||
- Added `db_session` property and `set_db_session()` method
|
- Added `db_session` parameter to `SeriesApp.__init__()`
|
||||||
- Added `init_from_db_async()` for async database initialization
|
- Added `db_session` property and `set_db_session()` method
|
||||||
- Created `get_series_app_with_db()` dependency that injects database session
|
- Added `init_from_db_async()` for async database initialization
|
||||||
- Added 6 new tests for database support in `test_series_app.py`
|
- Created `get_series_app_with_db()` dependency that injects database session
|
||||||
- All 815 unit tests and 55 API tests pass
|
- Added 6 new tests for database support in `test_series_app.py`
|
||||||
|
- All 815 unit tests and 55 API tests pass
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -351,9 +353,10 @@ async def lifespan(app: FastAPI):
|
|||||||
- Create sample data files for migration tests
|
- Create sample data files for migration tests
|
||||||
|
|
||||||
**Implementation Notes:**
|
**Implementation Notes:**
|
||||||
- Added 5 new integration tests to cover all required test cases
|
|
||||||
- All 11 migration integration tests pass
|
- Added 5 new integration tests to cover all required test cases
|
||||||
- All 870 tests pass (815 unit + 55 API)
|
- All 11 migration integration tests pass
|
||||||
|
- All 870 tests pass (815 unit + 55 API)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -383,10 +386,11 @@ async def lifespan(app: FastAPI):
|
|||||||
- Verify existing file-based tests still pass ✅
|
- Verify existing file-based tests still pass ✅
|
||||||
|
|
||||||
**Implementation Notes:**
|
**Implementation Notes:**
|
||||||
- Added deprecation warnings to Serie.save_to_file() and Serie.load_from_file()
|
|
||||||
- Added deprecation warning tests to test_serie_class.py
|
- Added deprecation warnings to Serie.save_to_file() and Serie.load_from_file()
|
||||||
- Updated infrastructure.md with Data Storage section
|
- Added deprecation warning tests to test_serie_class.py
|
||||||
- All 1012 tests pass (872 unit + 55 API + 85 integration)
|
- Updated infrastructure.md with Data Storage section
|
||||||
|
- All 1012 tests pass (872 unit + 55 API + 85 integration)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -35,6 +35,7 @@ from src.core.providers.base_provider import Loader
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from src.server.database.models import AnimeSeries
|
from src.server.database.models import AnimeSeries
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
@ -23,6 +23,7 @@ from src.core.entities.series import Serie
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from src.server.database.models import AnimeSeries
|
from src.server.database.models import AnimeSeries
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -51,6 +51,15 @@ async def lifespan(app: FastAPI):
|
|||||||
try:
|
try:
|
||||||
logger.info("Starting FastAPI application...")
|
logger.info("Starting FastAPI application...")
|
||||||
|
|
||||||
|
# Initialize database first (required for migration and other services)
|
||||||
|
try:
|
||||||
|
from src.server.database.connection import init_db
|
||||||
|
await init_db()
|
||||||
|
logger.info("Database initialized successfully")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Failed to initialize database: %s", e, exc_info=True)
|
||||||
|
raise # Database is required, fail startup if it fails
|
||||||
|
|
||||||
# Load configuration from config.json and sync with settings
|
# Load configuration from config.json and sync with settings
|
||||||
try:
|
try:
|
||||||
from src.server.services.config_service import get_config_service
|
from src.server.services.config_service import get_config_service
|
||||||
@ -128,6 +137,14 @@ async def lifespan(app: FastAPI):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error stopping download service: %s", e, exc_info=True)
|
logger.error("Error stopping download service: %s", e, exc_info=True)
|
||||||
|
|
||||||
|
# Close database connections
|
||||||
|
try:
|
||||||
|
from src.server.database.connection import close_db
|
||||||
|
await close_db()
|
||||||
|
logger.info("Database connections closed")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error closing database: %s", e, exc_info=True)
|
||||||
|
|
||||||
logger.info("FastAPI application shutdown complete")
|
logger.info("FastAPI application shutdown complete")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -291,8 +291,8 @@ class TestScanSavesToDatabase:
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_scan_async_saves_to_database(self):
|
async def test_scan_async_saves_to_database(self):
|
||||||
"""Test scan_async method saves series to database."""
|
"""Test scan_async method saves series to database."""
|
||||||
from src.core.SerieScanner import SerieScanner
|
|
||||||
from src.core.entities.series import Serie
|
from src.core.entities.series import Serie
|
||||||
|
from src.core.SerieScanner import SerieScanner
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
# Create series folder structure
|
# Create series folder structure
|
||||||
@ -408,8 +408,8 @@ class TestSearchAndAddWorkflow:
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_search_and_add_workflow(self):
|
async def test_search_and_add_workflow(self):
|
||||||
"""Test searching for anime and adding it saves to database."""
|
"""Test searching for anime and adding it saves to database."""
|
||||||
from src.core.SeriesApp import SeriesApp
|
|
||||||
from src.core.entities.series import Serie
|
from src.core.entities.series import Serie
|
||||||
|
from src.core.SeriesApp import SeriesApp
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
# Mock database
|
# Mock database
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user