Files
bakery-ia/services/forecasting/app/main.py

117 lines
3.9 KiB
Python
Raw Normal View History

2025-07-21 19:48:56 +02:00
# ================================================================
# services/forecasting/app/main.py
# ================================================================
"""
2025-07-21 19:48:56 +02:00
Forecasting Service Main Application
Demand prediction and forecasting service for bakery operations
"""
2025-07-18 14:41:39 +02:00
import structlog
2025-07-21 19:48:56 +02:00
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
2025-07-21 19:48:56 +02:00
from fastapi.responses import JSONResponse
from app.core.config import settings
2025-07-21 19:48:56 +02:00
from app.core.database import database_manager, get_db_health
from app.api import forecasts, predictions
from app.services.messaging import setup_messaging, cleanup_messaging
from shared.monitoring.logging import setup_logging
from shared.monitoring.metrics import MetricsCollector
2025-07-21 19:48:56 +02:00
# Setup structured logging
setup_logging("forecasting-service", settings.LOG_LEVEL)
2025-07-18 14:41:39 +02:00
logger = structlog.get_logger()
# Initialize metrics collector
metrics_collector = MetricsCollector("forecasting-service")
2025-07-21 19:48:56 +02:00
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Application lifespan manager for startup and shutdown events"""
# Startup
logger.info("Starting Forecasting Service", version="1.0.0")
try:
# Initialize database
logger.info("Initializing database connection")
await database_manager.create_tables()
logger.info("Database initialized successfully")
# Initialize messaging
logger.info("Setting up messaging")
await setup_messaging()
logger.info("Messaging initialized")
# Register custom metrics
metrics_collector.register_counter("forecasts_generated_total", "Total forecasts generated")
metrics_collector.register_counter("predictions_served_total", "Total predictions served")
metrics_collector.register_histogram("forecast_processing_time_seconds", "Time to process forecast request")
metrics_collector.register_gauge("active_models_count", "Number of active models")
# Start metrics server
metrics_collector.start_metrics_server(8080)
logger.info("Forecasting Service started successfully")
yield
except Exception as e:
logger.error("Failed to start Forecasting Service", error=str(e))
raise
finally:
# Shutdown
logger.info("Shutting down Forecasting Service")
try:
await cleanup_messaging()
logger.info("Messaging cleanup completed")
except Exception as e:
logger.error("Error during messaging cleanup", error=str(e))
# Create FastAPI app with lifespan
app = FastAPI(
title="Bakery Forecasting Service",
description="AI-powered demand prediction and forecasting service for bakery operations",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan
)
# CORS middleware
app.add_middleware(
CORSMiddleware,
2025-07-21 19:48:56 +02:00
allow_origins=settings.CORS_ORIGINS_LIST,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
2025-07-21 19:48:56 +02:00
# Include API routers
app.include_router(forecasts.router, prefix="/api/v1/forecasts", tags=["forecasts"])
app.include_router(predictions.router, prefix="/api/v1/predictions", tags=["predictions"])
@app.get("/health")
async def health_check():
"""Health check endpoint"""
2025-07-21 19:48:56 +02:00
db_health = await get_db_health()
return {
2025-07-21 19:48:56 +02:00
"status": "healthy" if db_health else "unhealthy",
"service": "forecasting-service",
2025-07-21 19:48:56 +02:00
"version": "1.0.0",
"database": "connected" if db_health else "disconnected",
"timestamp": structlog.get_logger().info("Health check requested")
}
2025-07-21 19:48:56 +02:00
@app.get("/metrics")
async def get_metrics():
"""Metrics endpoint for Prometheus"""
return metrics_collector.generate_latest()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
2025-07-21 19:48:56 +02:00