""" eamco_auto_api - FastAPI Automatic Delivery Microservice. This microservice provides endpoints for managing automatic oil delivery scheduling, fuel level estimation, and delivery confirmation. Endpoints: GET /health - Health check with database connectivity status GET /main/temp - Manually trigger temperature fetch GET /main/update/auto - Update fuel levels for auto-delivery customers GET /main/update/normal - Update fuel levels for normal customers GET /delivery/... - Delivery management endpoints POST /confirm/... - Delivery confirmation endpoints GET /fixstuff/auto/... - Auto-delivery fix/maintenance endpoints GET /fixstuff/customer/... - Customer fix/maintenance endpoints Usage: # Development uvicorn main:app --reload --host 0.0.0.0 --port 8000 # Production (Docker) docker run -p 8000:8000 eamco_auto_api """ import logging import sys import uuid import os from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from starlette.middleware.base import BaseHTTPMiddleware from sqlalchemy import create_engine, text from sqlalchemy.orm import sessionmaker from config import load_config from app.routers import main, delivery, confirm, fixstuff_auto, fixstuff_customer # ============================================================================= # CONFIGURATION # ============================================================================= ApplicationConfig = load_config() # ============================================================================= # LOGGING CONFIGURATION # ============================================================================= def setup_logging(): """Configure structured logging for the application.""" log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) root_logger = logging.getLogger() root_logger.setLevel(log_level) root_logger.handlers.clear() console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(log_level) console_handler.setFormatter(formatter) root_logger.addHandler(console_handler) logging.getLogger('uvicorn.access').setLevel(logging.WARNING) return logging.getLogger('eamco_auto_api') logger = setup_logging() # ============================================================================= # DATABASE SETUP # ============================================================================= engine = create_engine( ApplicationConfig.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True, pool_size=5, max_overflow=10, pool_recycle=3600, ) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) def check_db_connection(): """ Test database connectivity. """ try: db = SessionLocal() db.execute(text("SELECT 1")) db.close() return True except Exception: return False # ============================================================================= # FASTAPI APPLICATION # ============================================================================= app = FastAPI( title="eamco_auto_api", description="Automatic oil delivery scheduling and fuel estimation microservice", version="1.0.0", docs_url="/docs", redoc_url="/redoc", ) # ============================================================================= # MIDDLEWARE # ============================================================================= class RequestIDMiddleware(BaseHTTPMiddleware): """Request ID middleware for request tracking/correlation.""" async def dispatch(self, request: Request, call_next): request_id = request.headers.get("X-Request-ID") or str(uuid.uuid4())[:8] request.state.request_id = request_id response = await call_next(request) response.headers["X-Request-ID"] = request_id return response app.add_middleware(RequestIDMiddleware) app.add_middleware( CORSMiddleware, allow_origins=ApplicationConfig.origins, allow_credentials=True, allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], allow_headers=["Authorization", "Content-Type", "Accept", "Origin", "X-Requested-With"], ) # ============================================================================= # ROUTERS # ============================================================================= app.include_router(main.router) app.include_router(delivery.router) app.include_router(confirm.router) app.include_router(fixstuff_auto.router) app.include_router(fixstuff_customer.router) # ============================================================================= # ENDPOINTS # ============================================================================= @app.get("/", include_in_schema=False) async def root(): """Root endpoint - redirect to docs.""" return { "service": "eamco_auto_api", "version": "1.0.0", "docs": "/docs", } @app.get("/health", tags=["Health"]) async def health_check(): """ Health check endpoint. Returns service status and database connectivity. Use this endpoint for container health checks and monitoring. Returns: JSON with status and db_connected flag """ db_connected = check_db_connection() return { "status": "healthy" if db_connected else "degraded", "db_connected": db_connected, } # ============================================================================= # STARTUP/SHUTDOWN EVENTS # ============================================================================= @app.on_event("startup") async def startup_event(): """Application startup - log configuration and test DB connection.""" logger.info("🚀 eamco_auto_api STARTING") mode = ApplicationConfig.CURRENT_SETTINGS.upper() if mode in ['DEVELOPMENT', 'DEV']: logger.info("🤖🤖🤖🤖🤖 Mode: Development 🤖🤖🤖🤖🤖") elif mode in ['PRODUCTION', 'PROD']: logger.info("💀💀💀💀💀💀💀💀💀💀 ⚠️ WARNING PRODUCTION 💀💀💀💀💀💀💀💀💀💀") # Sanitize DB URI to avoid logging credentials db_uri = ApplicationConfig.SQLALCHEMY_DATABASE_URI if '@' in db_uri: db_uri = db_uri.split('@')[-1] # Only show host/db portion logger.info(f"DB: ...@{db_uri[:50]}") logger.info(f"CORS: {len(ApplicationConfig.origins)} origins configured") # Test database connection if check_db_connection(): logger.info("DB Connection: ✅ OK") else: logger.warning("DB Connection: ❌ FAILED") @app.on_event("shutdown") async def shutdown_event(): """Application shutdown - cleanup.""" logger.info("🛑 eamco_auto_api SHUTTING DOWN")