from contextlib import asynccontextmanager from datetime import datetime from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from pathlib import Path import logging import os from .config import settings from .database import init_oracle, close_oracle, init_sqlite # Configure logging with both stream and file handlers _log_level = getattr(logging, settings.LOG_LEVEL.upper(), logging.INFO) _log_format = '%(asctime)s | %(levelname)s | %(name)s | %(message)s' _formatter = logging.Formatter(_log_format) _stream_handler = logging.StreamHandler() _stream_handler.setFormatter(_formatter) _log_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'logs') os.makedirs(_log_dir, exist_ok=True) _log_filename = f"sync_comenzi_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" _file_handler = logging.FileHandler(os.path.join(_log_dir, _log_filename), encoding='utf-8') _file_handler.setFormatter(_formatter) _root_logger = logging.getLogger() _root_logger.setLevel(_log_level) _root_logger.addHandler(_stream_handler) _root_logger.addHandler(_file_handler) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Startup and shutdown events.""" logger.info("Starting GoMag Import Manager...") # Initialize Oracle pool try: init_oracle() except Exception as e: logger.error(f"Oracle init failed: {e}") # Allow app to start even without Oracle for development # Initialize SQLite init_sqlite() # Initialize scheduler (restore saved config) from .services import scheduler_service, sqlite_service scheduler_service.init_scheduler() try: config = await sqlite_service.get_scheduler_config() if config.get("enabled") == "True": interval = int(config.get("interval_minutes", "5")) scheduler_service.start_scheduler(interval) except Exception: pass logger.info("GoMag Import Manager started") yield # Shutdown scheduler_service.shutdown_scheduler() close_oracle() logger.info("GoMag Import Manager stopped") app = FastAPI( title="GoMag Import Manager", description="Import comenzi web GoMag → ROA Oracle", version="1.0.0", lifespan=lifespan ) # Static files and templates static_dir = Path(__file__).parent / "static" templates_dir = Path(__file__).parent / "templates" static_dir.mkdir(parents=True, exist_ok=True) (static_dir / "css").mkdir(exist_ok=True) (static_dir / "js").mkdir(exist_ok=True) templates_dir.mkdir(parents=True, exist_ok=True) app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") # Include routers from .routers import health, dashboard, mappings, articles, validation, sync app.include_router(health.router) app.include_router(dashboard.router) app.include_router(mappings.router) app.include_router(articles.router) app.include_router(validation.router) app.include_router(sync.router)