Merge pull request #133 from christianlouis/copilot/fix-system-start-issue

Migrate from deprecated @app.on_event to lifespan context manager
This commit is contained in:
Christian Krakau-Louis
2026-02-08 08:22:10 +01:00
committed by GitHub
+59 -51
View File
@@ -2,6 +2,7 @@
import os import os
import logging import logging
import pathlib import pathlib
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException, Request, status from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
@@ -34,7 +35,64 @@ if settings.auth_enabled and not settings.session_secret:
raise ValueError("SESSION_SECRET must be set when AUTH_ENABLED=True. Generate one with: python -c 'import secrets; print(secrets.token_hex(32))'") raise ValueError("SESSION_SECRET must be set when AUTH_ENABLED=True. Generate one with: python -c 'import secrets; print(secrets.token_hex(32))'")
SESSION_SECRET = settings.session_secret or "INSECURE_DEFAULT_FOR_DEVELOPMENT_ONLY_DO_NOT_USE_IN_PRODUCTION_MINIMUM_32_CHARS" SESSION_SECRET = settings.session_secret or "INSECURE_DEFAULT_FOR_DEVELOPMENT_ONLY_DO_NOT_USE_IN_PRODUCTION_MINIMUM_32_CHARS"
app = FastAPI(title="DocuElevate")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
Manage application lifespan events (startup and shutdown).
This replaces the deprecated @app.on_event decorators.
"""
# Startup: Initialize database
init_db() # Create tables if they don't exist
# Load settings from database after DB initialization
from app.database import SessionLocal
from app.utils.config_loader import load_settings_from_db
db = SessionLocal()
try:
load_settings_from_db(settings, db)
logging.info("Database settings loaded successfully")
except Exception as e:
logging.error(f"Failed to load database settings: {e}")
finally:
db.close()
# Force settings dump to log for troubleshooting
from app.utils.config_validator import dump_all_settings
dump_all_settings()
# Validate configuration
config_issues = check_all_configs()
# Log overall status
has_issues = any(config_issues['email']) or any(
len(issues) > 0 for provider, issues in config_issues['storage'].items()
)
if has_issues:
logging.warning("Application started with configuration issues - some features may be unavailable")
else:
logging.info("Application started with valid configuration")
logging.info("Router organization: Using refactored API routers from app/api/ directory")
# Initialize notification system
init_apprise()
# Send startup notification
notify_startup()
# Application is now running
yield
# Shutdown: Cleanup tasks
logging.info("Application shutting down")
# Send shutdown notification
notify_shutdown()
app = FastAPI(title="DocuElevate", lifespan=lifespan)
# 1) Session Middleware (for request.session to work) # 1) Session Middleware (for request.session to work)
app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET) app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET)
@@ -56,56 +114,6 @@ if os.path.exists(static_dir):
else: else:
print(f"WARNING: Static directory not found at {static_dir}. Static files will not be served.") print(f"WARNING: Static directory not found at {static_dir}. Static files will not be served.")
@app.on_event("startup")
def on_startup():
init_db() # Create tables if they don't exist
# Load settings from database after DB initialization
from app.database import SessionLocal
from app.utils.config_loader import load_settings_from_db
db = SessionLocal()
try:
load_settings_from_db(settings, db)
logging.info("Database settings loaded successfully")
except Exception as e:
logging.error(f"Failed to load database settings: {e}")
finally:
db.close()
@app.on_event("startup")
async def startup_event():
"""Run startup tasks for the application"""
# Force settings dump to log for troubleshooting
from app.utils.config_validator import dump_all_settings
dump_all_settings()
# Validate configuration
config_issues = check_all_configs()
# Log overall status
has_issues = any(config_issues['email']) or any(len(issues) > 0 for provider, issues in config_issues['storage'].items())
if has_issues:
logging.warning("Application started with configuration issues - some features may be unavailable")
else:
logging.info("Application started with valid configuration")
logging.info("Router organization: Using refactored API routers from app/api/ directory")
# Initialize notification system
init_apprise()
# Send startup notification
notify_startup()
@app.on_event("shutdown")
async def shutdown_event():
"""Run shutdown tasks for the application"""
logging.info("Application shutting down")
# Send shutdown notification
notify_shutdown()
# Custom exception handlers that return JSON for API routes and HTML for frontend routes # Custom exception handlers that return JSON for API routes and HTML for frontend routes
@app.exception_handler(HTTPException) @app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException): async def http_exception_handler(request: Request, exc: HTTPException):