Remove migration code and alembic dependency

This commit is contained in:
Lukas 2025-12-13 09:02:26 +01:00
parent 842f9c88eb
commit ee317b29f1
13 changed files with 58 additions and 83 deletions

View File

@ -17,7 +17,7 @@
"keep_days": 30 "keep_days": 30
}, },
"other": { "other": {
"master_password_hash": "$pbkdf2-sha256$29000$DgFgDIHwfk/p/X.PEULIGQ$baPkp2MQxqv8yolTjZ5Ks0fIl9g/Eer3YBE1jjR6qjc", "master_password_hash": "$pbkdf2-sha256$29000$tRZCyFnr/d87x/i/19p7Lw$BoD8EF67N97SRs7kIX8SREbotRwvFntS.WCH9ZwTxHY",
"anime_directory": "/home/lukas/Volume/serien/" "anime_directory": "/home/lukas/Volume/serien/"
}, },
"version": "1.0.0" "version": "1.0.0"

View File

@ -0,0 +1,24 @@
{
"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$nbNWSkkJIeTce48xxrh3bg$QXT6A63JqmSLimtTeI04HzC4eKfQS26xFW7UL9Ry5co",
"anime_directory": "/home/lukas/Volume/serien/"
},
"version": "1.0.0"
}

View File

@ -0,0 +1,24 @@
{
"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$j5HSWuu9V.rdm9Pa2zunNA$gjQqL753WLBMZtHVOhziVn.vW3Bkq8mGtCzSkbBjSHo",
"anime_directory": "/home/lukas/Volume/serien/"
},
"version": "1.0.0"
}

View File

@ -178,10 +178,6 @@ grep -rn "data-key\|data-folder\|data-series" src/server/web/templates/ --includ
- [ ] All CRUD operations use `key` for identification - [ ] All CRUD operations use `key` for identification
- [ ] Logging uses `key` in messages - [ ] Logging uses `key` in messages
3. **`src/server/database/migrations/`**
- [ ] Migration files maintain `key` as unique, indexed column
- [ ] No migrations that use `folder` as identifier
**Validation Commands:** **Validation Commands:**
```bash ```bash

View File

@ -60,10 +60,9 @@ Throughout the codebase, three identifiers are used for anime series:
**Valid examples**: `"attack-on-titan"`, `"one-piece"`, `"86-eighty-six"`, `"re-zero"` **Valid examples**: `"attack-on-titan"`, `"one-piece"`, `"86-eighty-six"`, `"re-zero"`
**Invalid examples**: `"Attack On Titan"`, `"attack_on_titan"`, `"attack on titan"` **Invalid examples**: `"Attack On Titan"`, `"attack_on_titan"`, `"attack on titan"`
### Migration Notes ### Notes
- **Backward Compatibility**: API endpoints accepting `anime_id` will check `key` first, then fall back to `folder` lookup - **Backward Compatibility**: API endpoints accepting `anime_id` will check `key` first, then fall back to `folder` lookup
- **Deprecation**: Folder-based lookups are deprecated and will be removed in a future version
- **New Code**: Always use `key` for identification; `folder` is metadata only - **New Code**: Always use `key` for identification; `folder` is metadata only
## API Endpoints ## API Endpoints

View File

@ -14,5 +14,4 @@ pytest==7.4.3
pytest-asyncio==0.21.1 pytest-asyncio==0.21.1
httpx==0.25.2 httpx==0.25.2
sqlalchemy>=2.0.35 sqlalchemy>=2.0.35
alembic==1.13.0
aiosqlite>=0.19.0 aiosqlite>=0.19.0

View File

@ -7,7 +7,7 @@
# installs dependencies, sets up the database, and starts the application. # installs dependencies, sets up the database, and starts the application.
# #
# Usage: # Usage:
# ./start.sh [development|production] [--no-install] [--no-migrate] # ./start.sh [development|production] [--no-install]
# #
# Environment Variables: # Environment Variables:
# ENVIRONMENT: 'development' or 'production' (default: development) # ENVIRONMENT: 'development' or 'production' (default: development)
@ -28,7 +28,6 @@ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
CONDA_ENV="${CONDA_ENV:-AniWorld}" CONDA_ENV="${CONDA_ENV:-AniWorld}"
ENVIRONMENT="${1:-development}" ENVIRONMENT="${1:-development}"
INSTALL_DEPS="${INSTALL_DEPS:-true}" INSTALL_DEPS="${INSTALL_DEPS:-true}"
RUN_MIGRATIONS="${RUN_MIGRATIONS:-true}"
PORT="${PORT:-8000}" PORT="${PORT:-8000}"
HOST="${HOST:-127.0.0.1}" HOST="${HOST:-127.0.0.1}"
@ -104,20 +103,6 @@ install_dependencies() {
log_success "Dependencies installed." log_success "Dependencies installed."
} }
# Run database migrations
run_migrations() {
if [[ "$RUN_MIGRATIONS" != "true" ]]; then
log_warning "Skipping database migrations."
return
fi
log_info "Running database migrations..."
cd "$PROJECT_ROOT"
conda run -n "$CONDA_ENV" \
python -m alembic upgrade head 2>/dev/null || log_warning "No migrations to run."
log_success "Database migrations completed."
}
# Initialize database # Initialize database
init_database() { init_database() {
log_info "Initializing database..." log_info "Initializing database..."
@ -220,10 +205,6 @@ main() {
INSTALL_DEPS="false" INSTALL_DEPS="false"
shift shift
;; ;;
--no-migrate)
RUN_MIGRATIONS="false"
shift
;;
*) *)
ENVIRONMENT="$1" ENVIRONMENT="$1"
shift shift
@ -237,7 +218,6 @@ main() {
create_env_file create_env_file
install_dependencies install_dependencies
init_database init_database
run_migrations
start_application start_application
} }

View File

@ -31,7 +31,6 @@ async def setup_auth(req: SetupRequest):
This endpoint also initializes the configuration with default values This endpoint also initializes the configuration with default values
and saves the anime directory and master password hash. and saves the anime directory and master password hash.
If anime_directory is provided, runs migration for existing data files.
""" """
if auth_service.is_configured(): if auth_service.is_configured():
raise HTTPException( raise HTTPException(

View File

@ -214,14 +214,14 @@ def update_advanced_config(
async def update_directory( async def update_directory(
directory_config: Dict[str, str], auth: dict = Depends(require_auth) directory_config: Dict[str, str], auth: dict = Depends(require_auth)
) -> Dict[str, Any]: ) -> Dict[str, Any]:
"""Update anime directory configuration and run migration. """Update anime directory configuration.
Args: Args:
directory_config: Dictionary with 'directory' key directory_config: Dictionary with 'directory' key
auth: Authentication token (required) auth: Authentication token (required)
Returns: Returns:
Success message with optional migration results Success message
""" """
try: try:
directory = directory_config.get("directory") directory = directory_config.get("directory")

View File

@ -13,7 +13,7 @@ This package provides persistent storage for anime series, episodes, download qu
Install required dependencies: Install required dependencies:
```bash ```bash
pip install sqlalchemy alembic aiosqlite pip install sqlalchemy aiosqlite
``` ```
Or use the project requirements: Or use the project requirements:
@ -163,24 +163,6 @@ from src.config.settings import settings
settings.database_url = "sqlite:///./data/aniworld.db" settings.database_url = "sqlite:///./data/aniworld.db"
``` ```
## Migrations (Future)
Alembic is installed for database migrations:
```bash
# Initialize Alembic
alembic init alembic
# Generate migration
alembic revision --autogenerate -m "Description"
# Apply migrations
alembic upgrade head
# Rollback
alembic downgrade -1
```
## Testing ## Testing
Run database tests: Run database tests:
@ -196,7 +178,6 @@ The test suite uses an in-memory SQLite database for isolation and speed.
- **base.py**: Base declarative class and mixins - **base.py**: Base declarative class and mixins
- **models.py**: SQLAlchemy ORM models (4 models) - **models.py**: SQLAlchemy ORM models (4 models)
- **connection.py**: Engine, session factory, dependency injection - **connection.py**: Engine, session factory, dependency injection
- **migrations.py**: Alembic migration placeholder
- ****init**.py**: Package exports - ****init**.py**: Package exports
- **service.py**: Service layer with CRUD operations - **service.py**: Service layer with CRUD operations
@ -432,5 +413,4 @@ Solution: Ensure referenced records exist before creating relationships.
## Further Reading ## Further Reading
- [SQLAlchemy 2.0 Documentation](https://docs.sqlalchemy.org/en/20/) - [SQLAlchemy 2.0 Documentation](https://docs.sqlalchemy.org/en/20/)
- [Alembic Tutorial](https://alembic.sqlalchemy.org/en/latest/tutorial.html)
- [FastAPI with Databases](https://fastapi.tiangolo.com/tutorial/sql-databases/) - [FastAPI with Databases](https://fastapi.tiangolo.com/tutorial/sql-databases/)

View File

@ -313,7 +313,6 @@ async def get_schema_version(engine: Optional[AsyncEngine] = None) -> str:
"""Get current database schema version. """Get current database schema version.
Returns version string based on existing tables and structure. Returns version string based on existing tables and structure.
For production, consider using Alembic versioning.
Args: Args:
engine: Optional database engine (uses default if not provided) engine: Optional database engine (uses default if not provided)

View File

@ -51,7 +51,7 @@ 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) # Initialize database first (required for other services)
try: try:
from src.server.database.connection import init_db from src.server.database.connection import init_db
await init_db() await init_db()

View File

@ -4,7 +4,7 @@ This service handles:
- Loading and saving configuration to JSON files - Loading and saving configuration to JSON files
- Configuration validation - Configuration validation
- Backup and restore functionality - Backup and restore functionality
- Configuration migration for version updates - Configuration version management
""" """
import json import json
@ -35,8 +35,8 @@ class ConfigBackupError(ConfigServiceError):
class ConfigService: class ConfigService:
"""Service for managing application configuration persistence. """Service for managing application configuration persistence.
Handles loading, saving, validation, backup, and migration of Handles loading, saving, validation, backup, and version management
configuration files. Uses JSON format for human-readable and of configuration files. Uses JSON format for human-readable and
version-control friendly storage. version-control friendly storage.
""" """
@ -84,11 +84,6 @@ class ConfigService:
with open(self.config_path, "r", encoding="utf-8") as f: with open(self.config_path, "r", encoding="utf-8") as f:
data = json.load(f) data = json.load(f)
# Check if migration is needed
file_version = data.get("version", "1.0.0")
if file_version != self.CONFIG_VERSION:
data = self._migrate_config(data, file_version)
# Remove version key before constructing AppConfig # Remove version key before constructing AppConfig
data.pop("version", None) data.pop("version", None)
@ -329,26 +324,6 @@ class ConfigService:
# Ignore errors during cleanup # Ignore errors during cleanup
continue continue
def _migrate_config(
self, data: Dict, from_version: str # noqa: ARG002
) -> Dict:
"""Migrate configuration from old version to current.
Args:
data: Configuration data to migrate
from_version: Version to migrate from (reserved for future use)
Returns:
Dict: Migrated configuration data
"""
# Currently only one version exists
# Future migrations would go here
# Example:
# if from_version == "1.0.0" and self.CONFIG_VERSION == "2.0.0":
# data = self._migrate_1_0_to_2_0(data)
return data
# Singleton instance # Singleton instance
_config_service: Optional[ConfigService] = None _config_service: Optional[ConfigService] = None