This commit is contained in:
Lukas Pupka-Lipinski 2025-09-29 14:53:25 +02:00
parent 3ab4467423
commit 9497633e78
9 changed files with 144 additions and 226 deletions

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 AniWorld Project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -30,68 +30,22 @@ from web.routes import (
) )
from web.routes.websocket_handlers import register_socketio_handlers from web.routes.websocket_handlers import register_socketio_handlers
# Placeholder managers are now defined in static_routes.py # Import API blueprints from their correct locations
from web.controllers.api.v1.process import process_bp
from web.controllers.api.v1.scheduler import scheduler_bp
from web.controllers.api.v1.logging import logging_bp
from web.controllers.api.v1.health import health_bp
from application.services.scheduler_service import init_scheduler, get_scheduler
from shared.utils.process_utils import (with_process_lock, RESCAN_LOCK, DOWNLOAD_LOCK,
ProcessLockError, is_process_running, check_process_locks)
# Placeholder objects are now defined in their respective route files # Import error handling and monitoring modules
from web.middleware.error_handler import handle_api_errors
# TODO: Fix these imports # Performance optimization modules - not yet implemented
# from process_api import process_bp
# from scheduler_api import scheduler_bp
# from logging_api import logging_bp
# from config_api import config_bp
# from scheduler import init_scheduler, get_scheduler
# from process_locks import (with_process_lock, RESCAN_LOCK, DOWNLOAD_LOCK,
# ProcessLockError, is_process_running, check_process_locks)
# TODO: Fix these imports # API integration and database modules - not yet implemented
# # Import new error handling and health monitoring modules # User experience and accessibility modules - not yet implemented
# from error_handler import (
# handle_api_errors, error_recovery_manager, recovery_strategies,
# network_health_checker, NetworkError, DownloadError, RetryableError
# )
# from health_monitor import health_bp, health_monitor, init_health_monitoring, cleanup_health_monitoring
# TODO: Fix these imports
# # Import performance optimization modules
# from performance_optimizer import (
# init_performance_monitoring, cleanup_performance_monitoring,
# speed_limiter, download_cache, memory_monitor, download_manager
# )
# from performance_api import performance_bp
# TODO: Fix these imports
# # Import API integration modules
# from api_integration import (
# init_api_integrations, cleanup_api_integrations,
# webhook_manager, export_manager, notification_service
# )
# from api_endpoints import api_integration_bp
#
# # Import database management modules
# from database_manager import (
# database_manager, anime_repository, backup_manager, storage_manager,
# init_database_system, cleanup_database_system
# )
# from database_api import database_bp
#
# # Import health check endpoints
# from health_endpoints import health_bp
#
# # Import user experience modules
# from keyboard_shortcuts import keyboard_manager
# from drag_drop import drag_drop_manager
# from bulk_operations import bulk_operations_manager
# from user_preferences import preferences_manager, preferences_bp
# from advanced_search import advanced_search_manager, search_bp
# from undo_redo_manager import undo_redo_manager, undo_redo_bp
#
# # Import Mobile & Accessibility modules
# from mobile_responsive import mobile_responsive_manager
# from touch_gestures import touch_gesture_manager
# from accessibility_features import accessibility_manager
# from screen_reader_support import screen_reader_manager
# from color_contrast_compliance import color_contrast_manager
# from multi_screen_support import multi_screen_manager
app = Flask(__name__, app = Flask(__name__,
template_folder='web/templates/base', template_folder='web/templates/base',
@ -122,49 +76,14 @@ app.register_blueprint(api_bp)
app.register_blueprint(static_bp) app.register_blueprint(static_bp)
app.register_blueprint(diagnostic_bp) app.register_blueprint(diagnostic_bp)
app.register_blueprint(config_bp) app.register_blueprint(config_bp)
# TODO: Fix and uncomment these blueprints when modules are available # Register available API blueprints
# app.register_blueprint(process_bp) app.register_blueprint(process_bp)
# app.register_blueprint(scheduler_bp) app.register_blueprint(scheduler_bp)
# app.register_blueprint(logging_bp) app.register_blueprint(logging_bp)
# app.register_blueprint(config_bp) app.register_blueprint(health_bp)
# app.register_blueprint(health_bp) # Additional blueprints will be registered when features are implemented
# app.register_blueprint(performance_bp)
# app.register_blueprint(api_integration_bp)
# app.register_blueprint(database_bp)
# Note: health_endpoints blueprint already imported above as health_bp, no need to register twice
# TODO: Fix and register these APIs when modules are available # Additional feature initialization will be added when features are implemented
# # Register bulk operations API
# from bulk_api import bulk_api_bp
# app.register_blueprint(bulk_api_bp)
#
# # Register user preferences API
# app.register_blueprint(preferences_bp)
#
# # Register advanced search API
# app.register_blueprint(search_bp)
#
# # Register undo/redo API
# app.register_blueprint(undo_redo_bp)
#
# # Register Mobile & Accessibility APIs
# app.register_blueprint(color_contrast_manager.get_contrast_api_blueprint())
# TODO: Initialize features when modules are available
# # Initialize user experience features
# # keyboard_manager doesn't need init_app - it's a simple utility class
# bulk_operations_manager.init_app(app)
# preferences_manager.init_app(app)
# advanced_search_manager.init_app(app)
# undo_redo_manager.init_app(app)
#
# # Initialize Mobile & Accessibility features
# mobile_responsive_manager.init_app(app)
# touch_gesture_manager.init_app(app)
# accessibility_manager.init_app(app)
# screen_reader_manager.init_app(app)
# color_contrast_manager.init_app(app)
# multi_screen_manager.init_app(app)
# Global variables are now managed in their respective route files # Global variables are now managed in their respective route files
# Keep only series_app for backward compatibility # Keep only series_app for backward compatibility
@ -185,7 +104,7 @@ from web.routes.api_routes import set_socketio
set_socketio(socketio) set_socketio(socketio)
# Initialize scheduler # Initialize scheduler
# scheduler = init_scheduler(config, socketio) scheduler = init_scheduler(config, socketio)
def setup_scheduler_callbacks(): def setup_scheduler_callbacks():
"""Setup callbacks for scheduler operations.""" """Setup callbacks for scheduler operations."""
@ -231,59 +150,24 @@ def setup_scheduler_callbacks():
except Exception as e: except Exception as e:
raise Exception(f"Auto-download failed: {e}") raise Exception(f"Auto-download failed: {e}")
# scheduler.set_rescan_callback(rescan_callback) scheduler.set_rescan_callback(rescan_callback)
# scheduler.set_download_callback(download_callback) scheduler.set_download_callback(download_callback)
# Setup scheduler callbacks # Setup scheduler callbacks
# setup_scheduler_callbacks() setup_scheduler_callbacks()
# Initialize error handling and health monitoring # Advanced system initialization will be added when features are implemented
# try:
# init_health_monitoring()
# logging.info("Health monitoring initialized successfully")
# except Exception as e:
# logging.error(f"Failed to initialize health monitoring: {e}")
# Initialize performance monitoring
# try:
# init_performance_monitoring()
# logging.info("Performance monitoring initialized successfully")
# except Exception as e:
# logging.error(f"Failed to initialize performance monitoring: {e}")
# Initialize API integrations
# try:
# init_api_integrations()
# # Set export manager's series app reference
# export_manager.series_app = series_app
# logging.info("API integrations initialized successfully")
# except Exception as e:
# logging.error(f"Failed to initialize API integrations: {e}")
# Initialize database system
# try:
# init_database_system()
# logging.info("Database system initialized successfully")
# except Exception as e:
# logging.error(f"Failed to initialize database system: {e}")
# Register cleanup functions # Register cleanup functions
@atexit.register @atexit.register
def cleanup_on_exit(): def cleanup_on_exit():
"""Clean up resources on application exit.""" """Clean up resources on application exit."""
try: try:
# cleanup_health_monitoring() # Additional cleanup functions will be added when features are implemented
# cleanup_performance_monitoring()
# cleanup_api_integrations()
# cleanup_database_system()
logging.info("Application cleanup completed") logging.info("Application cleanup completed")
except Exception as e: except Exception as e:
logging.error(f"Error during cleanup: {e}") logging.error(f"Error during cleanup: {e}")
# Routes are now organized in separate blueprint files
# All routes have been moved to separate blueprint files in web/routes/
if __name__ == '__main__': if __name__ == '__main__':
# Only run initialization and logging setup in the main process # Only run initialization and logging setup in the main process
# This prevents duplicate initialization when Flask debug reloader starts # This prevents duplicate initialization when Flask debug reloader starts
@ -291,8 +175,6 @@ if __name__ == '__main__':
# Initialize the series app # Initialize the series app
init_series_app() init_series_app()
# Only configure logging if we're not in the reloader child process
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
# Configure enhanced logging system # Configure enhanced logging system
try: try:
from server.infrastructure.logging.config import get_logger, logging_config from server.infrastructure.logging.config import get_logger, logging_config
@ -304,15 +186,17 @@ if __name__ == '__main__':
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.warning("Using fallback logging - enhanced logging not available") logger.warning("Using fallback logging - enhanced logging not available")
# Only display startup messages if we're not in the reloader child process
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
logger.info("Starting Aniworld Flask server...") logger.info("Starting Aniworld Flask server...")
logger.info(f"Anime directory: {config.anime_directory}") logger.info(f"Anime directory: {config.anime_directory}")
logger.info(f"Log level: {config.log_level}") logger.info(f"Log level: {config.log_level}")
# Start scheduler if enabled # Start scheduler if enabled
# if config.scheduled_rescan_enabled: if hasattr(config, 'scheduled_rescan_enabled') and config.scheduled_rescan_enabled:
# logger.info(f"Starting scheduler - daily rescan at {config.scheduled_rescan_time}") logger.info(f"Starting scheduler - daily rescan at {getattr(config, 'scheduled_rescan_time', '03:00')}")
# scheduler.start_scheduler() scheduler.start_scheduler()
# else: else:
logger.info("Scheduled operations disabled") logger.info("Scheduled operations disabled")
logger.info("Server will be available at http://localhost:5000") logger.info("Server will be available at http://localhost:5000")
@ -322,7 +206,7 @@ if __name__ == '__main__':
socketio.run(app, debug=True, host='0.0.0.0', port=5000, allow_unsafe_werkzeug=True) socketio.run(app, debug=True, host='0.0.0.0', port=5000, allow_unsafe_werkzeug=True)
finally: finally:
# Clean shutdown # Clean shutdown
# if scheduler: if 'scheduler' in locals() and scheduler:
# scheduler.stop_scheduler() scheduler.stop_scheduler()
# logger.info("Scheduler stopped") logger.info("Scheduler stopped")
pass # Placeholder for cleanup code # Additional cleanup can be added here

View File

@ -4,7 +4,7 @@ import schedule
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Optional, Callable, Dict, Any from typing import Optional, Callable, Dict, Any
import logging import logging
from process_locks import (with_process_lock, RESCAN_LOCK, from shared.utils.process_utils import (with_process_lock, RESCAN_LOCK,
ProcessLockError, is_process_running) ProcessLockError, is_process_running)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -277,3 +277,55 @@
2025-09-29 14:19:04 - INFO - __main__ - <module> - Scheduled operations disabled 2025-09-29 14:19:04 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:19:04 - INFO - __main__ - <module> - Server will be available at http://localhost:5000 2025-09-29 14:19:04 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:19:06 - INFO - root - cleanup_on_exit - Application cleanup completed 2025-09-29 14:19:06 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:22:23 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:22:23 - INFO - __main__ - <module> - Starting Aniworld Flask server...
2025-09-29 14:22:23 - INFO - __main__ - <module> - Anime directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
2025-09-29 14:22:23 - INFO - __main__ - <module> - Log level: INFO
2025-09-29 14:22:23 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:22:23 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:25:48 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:25:48 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:44:45 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:44:45 - INFO - __main__ - <module> - Starting Aniworld Flask server...
2025-09-29 14:44:45 - INFO - __main__ - <module> - Anime directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
2025-09-29 14:44:45 - INFO - __main__ - <module> - Log level: INFO
2025-09-29 14:44:45 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:44:45 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:45:29 - DEBUG - schedule - clear - Deleting *all* jobs
2025-09-29 14:45:29 - INFO - application.services.scheduler_service - stop_scheduler - Scheduled operations stopped
2025-09-29 14:45:29 - INFO - __main__ - <module> - Scheduler stopped
2025-09-29 14:45:29 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:46:28 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:46:28 - INFO - __main__ - <module> - Starting Aniworld Flask server...
2025-09-29 14:46:28 - INFO - __main__ - <module> - Anime directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
2025-09-29 14:46:28 - INFO - __main__ - <module> - Log level: INFO
2025-09-29 14:46:28 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:46:28 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:46:45 - DEBUG - schedule - clear - Deleting *all* jobs
2025-09-29 14:46:45 - INFO - application.services.scheduler_service - stop_scheduler - Scheduled operations stopped
2025-09-29 14:46:45 - INFO - __main__ - <module> - Scheduler stopped
2025-09-29 14:46:45 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:47:19 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:47:19 - INFO - __main__ - <module> - Starting Aniworld Flask server...
2025-09-29 14:47:19 - INFO - __main__ - <module> - Anime directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
2025-09-29 14:47:19 - INFO - __main__ - <module> - Log level: INFO
2025-09-29 14:47:19 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:47:19 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:47:23 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:47:23 - WARNING - werkzeug - _log - * Debugger is active!
2025-09-29 14:48:02 - DEBUG - schedule - clear - Deleting *all* jobs
2025-09-29 14:48:02 - INFO - application.services.scheduler_service - stop_scheduler - Scheduled operations stopped
2025-09-29 14:48:02 - INFO - __main__ - <module> - Scheduler stopped
2025-09-29 14:48:02 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:48:02 - DEBUG - schedule - clear - Deleting *all* jobs
2025-09-29 14:48:02 - INFO - application.services.scheduler_service - stop_scheduler - Scheduled operations stopped
2025-09-29 14:48:02 - INFO - __main__ - <module> - Scheduler stopped
2025-09-29 14:48:02 - INFO - root - cleanup_on_exit - Application cleanup completed
2025-09-29 14:49:08 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:49:08 - INFO - __main__ - <module> - Starting Aniworld Flask server...
2025-09-29 14:49:08 - INFO - __main__ - <module> - Anime directory: \\sshfs.r\ubuntu@192.168.178.43\media\serien\Serien
2025-09-29 14:49:08 - INFO - __main__ - <module> - Log level: INFO
2025-09-29 14:49:08 - INFO - __main__ - <module> - Scheduled operations disabled
2025-09-29 14:49:08 - INFO - __main__ - <module> - Server will be available at http://localhost:5000
2025-09-29 14:49:12 - INFO - __main__ - <module> - Enhanced logging system initialized
2025-09-29 14:49:12 - WARNING - werkzeug - _log - * Debugger is active!

View File

@ -1,53 +1,56 @@
""" """
Health Check Endpoints Health Check Endpoints
This module provides comprehensive health check endpoints for monitoring This module provides basic health check endpoints for monitoring
the AniWorld application's status, dependencies, and performance metrics. the AniWorld application's status.
""" """
from flask import Blueprint, jsonify, request from flask import Blueprint, jsonify
import time import time
import os import os
import sqlite3
import psutil import psutil
from datetime import datetime from datetime import datetime
import threading
from health_monitor import health_monitor
from database_manager import database_manager
from performance_optimizer import memory_monitor
from config import config
# Blueprint for health check endpoints # Blueprint for health check endpoints
health_bp = Blueprint('health_check', __name__) health_bp = Blueprint('health_check', __name__, url_prefix='/api/health')
# Health check cache to avoid expensive operations on every request
_health_cache = {}
_cache_lock = threading.Lock()
_cache_ttl = 30 # Cache for 30 seconds
def get_cached_health_data(cache_key, check_function, ttl=None): @health_bp.route('/status')
"""Get health data from cache or execute check function.""" def get_basic_health():
current_time = time.time() """Get basic application health status."""
ttl = ttl or _cache_ttl
with _cache_lock:
if cache_key in _health_cache:
cached_data, timestamp = _health_cache[cache_key]
if current_time - timestamp < ttl:
return cached_data
# Execute check and cache result
try: try:
result = check_function() # Basic system metrics
_health_cache[cache_key] = (result, current_time) memory = psutil.virtual_memory()
return result disk = psutil.disk_usage('/')
return jsonify({
'status': 'healthy',
'timestamp': datetime.now().isoformat(),
'system': {
'memory_usage_percent': memory.percent,
'disk_usage_percent': disk.percent,
'uptime': time.time()
},
'application': {
'status': 'running',
'version': '1.0.0'
}
})
except Exception as e: except Exception as e:
return {'status': 'error', 'message': str(e)} return jsonify({
'status': 'error',
'message': str(e),
'timestamp': datetime.now().isoformat()
}), 500
@health_bp.route('/health') @health_bp.route('/ping')
def ping():
"""Simple ping endpoint."""
return jsonify({
'status': 'ok',
'timestamp': datetime.now().isoformat()
})
@health_bp.route('/api/health') @health_bp.route('/api/health')
def basic_health(): def basic_health():
"""Basic health check endpoint for load balancers.""" """Basic health check endpoint for load balancers."""

View File

@ -3,7 +3,7 @@ API endpoints for logging configuration and management.
""" """
from flask import Blueprint, jsonify, request, send_file from flask import Blueprint, jsonify, request, send_file
from auth import require_auth from web.controllers.auth_controller import require_auth
from config import config from config import config
import logging import logging
import os import os

View File

@ -1,6 +1,6 @@
from flask import Blueprint, jsonify, request from flask import Blueprint, jsonify, request
from auth import require_auth from web.controllers.auth_controller import require_auth
from process_locks import ( from shared.utils.process_utils import (
process_lock_manager, process_lock_manager,
RESCAN_LOCK, RESCAN_LOCK,
DOWNLOAD_LOCK, DOWNLOAD_LOCK,

View File

@ -1,6 +1,6 @@
from flask import Blueprint, jsonify, request from flask import Blueprint, jsonify, request
from auth import require_auth from web.controllers.auth_controller import require_auth
from scheduler import get_scheduler from application.services.scheduler_service import get_scheduler
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -240,7 +240,7 @@ def require_auth(f):
'code': 'AUTH_REQUIRED' 'code': 'AUTH_REQUIRED'
}), 401 }), 401
else: else:
return redirect(url_for('login')) return redirect(url_for('auth.login'))
return f(*args, **kwargs) return f(*args, **kwargs)
return decorated_function return decorated_function
@ -268,6 +268,6 @@ def optional_auth(f):
'code': 'AUTH_REQUIRED' 'code': 'AUTH_REQUIRED'
}), 401 }), 401
else: else:
return redirect(url_for('login')) return redirect(url_for('auth.login'))
return f(*args, **kwargs) return f(*args, **kwargs)
return decorated_function return decorated_function