Spaces:
Configuration error
Configuration error
| """ | |
| Main FastAPI application for Workforce Microservice. | |
| """ | |
| import os | |
| import time | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, Request, status | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from fastapi.exceptions import RequestValidationError | |
| from jose import JWTError | |
| from app.cache import connect_to_redis, close_redis_connection | |
| from app.core.config import settings | |
| from app.core.logging import get_logger, setup_logging | |
| from app.nosql import connect_to_mongo, close_mongo_connection | |
| from app.postgres import connect_to_postgres, close_postgres_connection | |
| from app.live_tracking.controllers.router import router as live_tracking_router | |
| from app.attendance.controllers.router import router as attendance_router | |
| # Logging setup | |
| log_level = settings.LOG_LEVEL.strip().upper() | |
| if log_level not in ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"): | |
| log_level = "INFO" | |
| setup_logging(level=log_level) | |
| logger = get_logger(__name__) | |
| async def lifespan(app: FastAPI): | |
| logger.info("Starting Workforce Microservice", extra={"event": "service_starting"}) | |
| await connect_to_mongo() | |
| await connect_to_postgres() | |
| await connect_to_redis() | |
| logger.info("Workforce Microservice started", extra={"event": "service_ready"}) | |
| yield | |
| logger.info("Shutting down Workforce Microservice", extra={"event": "service_stopping"}) | |
| await close_mongo_connection() | |
| await close_postgres_connection() | |
| await close_redis_connection() | |
| logger.info("Workforce Microservice stopped", extra={"event": "service_stopped"}) | |
| app = FastAPI( | |
| title="Workforce Microservice", | |
| description="Workforce management β profiles, scheduling, and attendance.", | |
| version="1.0.0", | |
| docs_url="/docs", | |
| redoc_url="/redoc", | |
| root_path=os.getenv("ROOT_PATH", ""), | |
| lifespan=lifespan, | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=settings.CORS_ORIGINS, | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| expose_headers=["*"], | |
| ) | |
| async def log_requests(request: Request, call_next): | |
| start = time.time() | |
| response = await call_next(request) | |
| logger.info( | |
| "HTTP request", | |
| extra={ | |
| "event": "http_request", | |
| "method": request.method, | |
| "path": request.url.path, | |
| "status_code": response.status_code, | |
| "duration_ms": round((time.time() - start) * 1000, 2), | |
| "client_ip": request.client.host if request.client else None, | |
| }, | |
| ) | |
| return response | |
| async def health_check(): | |
| return {"status": "healthy", "service": "workforce-ms", "version": app.version} | |
| # ββ Routers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| app.include_router(live_tracking_router) | |
| app.include_router(attendance_router) | |
| # ββ Exception handlers βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async def validation_exception_handler(request: Request, exc: RequestValidationError): | |
| errors = [ | |
| {"field": " -> ".join(str(loc) for loc in e["loc"]), "message": e["msg"], "type": e["type"]} | |
| for e in exc.errors() | |
| ] | |
| logger.warning("Validation error", extra={"event": "request_validation_failure", "errors": errors}) | |
| return JSONResponse( | |
| status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, | |
| content={"success": False, "error": "Validation Error", "errors": errors}, | |
| ) | |
| async def jwt_exception_handler(request: Request, exc: JWTError): | |
| return JSONResponse( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| content={"success": False, "error": "Unauthorized", "detail": str(exc)}, | |
| ) | |
| async def generic_exception_handler(request: Request, exc: Exception): | |
| logger.error("Unhandled exception", extra={"path": request.url.path}, exc_info=exc) | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content={"success": False, "error": "Internal Server Error"}, | |
| ) | |