feat: Always init DB on startup (required for SQLite fallback), add /api/v1/health endpoint

#5
Files changed (1) hide show
  1. brain/app/main.py +34 -25
brain/app/main.py CHANGED
@@ -47,24 +47,17 @@ async def lifespan(app: FastAPI):
47
  # Startup
48
  logger.info(f"Starting {settings.app_title} v{settings.app_version} (env={settings.app_env})")
49
 
50
- if not settings.is_production:
51
- try:
52
- from app.database import init_db
53
- await init_db()
54
- logger.info("Database tables initialized (dev mode)")
55
- except Exception as e:
56
- logger.warning(f"Database unavailable - running without persistence: {e}")
57
- else:
58
- # In production, just verify connectivity
59
- try:
60
- from app.database import check_db_health
61
- healthy = await check_db_health()
62
- if healthy:
63
- logger.info("Database connected successfully")
64
- else:
65
- logger.warning("Database health check failed - some endpoints may not work")
66
- except Exception as e:
67
- logger.warning(f"Database check failed: {e}")
68
 
69
  yield
70
  # Shutdown
@@ -98,8 +91,8 @@ app = FastAPI(
98
  - `GET /api/v1/agent-events/stream` - SSE stream for agent events
99
  """,
100
  lifespan=lifespan,
101
- docs_url="/docs" if not settings.is_production else None,
102
- redoc_url="/redoc" if not settings.is_production else None,
103
  )
104
 
105
 
@@ -109,14 +102,14 @@ async def global_exception_handler(request: Request, exc: Exception):
109
  logger.error(f"Unhandled error on {request.method} {request.url.path}: {exc}", exc_info=True)
110
  return JSONResponse(
111
  status_code=500,
112
- content={"detail": "Internal server error"},
113
  )
114
 
115
 
116
- # Add CORS middleware with configurable origins
117
  app.add_middleware(
118
  CORSMiddleware,
119
- allow_origins=settings.cors_origin_list,
120
  allow_credentials=True,
121
  allow_methods=["*"],
122
  allow_headers=["*"],
@@ -147,6 +140,7 @@ async def root():
147
  "status": "healthy",
148
  "service": settings.app_title,
149
  "version": settings.app_version,
 
150
  }
151
 
152
 
@@ -155,10 +149,25 @@ async def health_check():
155
  """Health check endpoint with actual DB verification."""
156
  from app.database import check_db_health
157
  db_ok = await check_db_health()
158
- status = "healthy" if db_ok else "degraded"
159
  return {
160
- "status": status,
161
  "database": "connected" if db_ok else "disconnected",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
163
 
164
 
 
47
  # Startup
48
  logger.info(f"Starting {settings.app_title} v{settings.app_version} (env={settings.app_env})")
49
 
50
+ # Always initialize the database (creates tables for SQLite fallback)
51
+ try:
52
+ from app.database import init_db, check_db_health
53
+ await init_db()
54
+ healthy = await check_db_health()
55
+ if healthy:
56
+ logger.info("Database initialized and connected")
57
+ else:
58
+ logger.warning("Database init succeeded but health check failed")
59
+ except Exception as e:
60
+ logger.warning(f"Database initialization failed - running without persistence: {e}")
 
 
 
 
 
 
 
61
 
62
  yield
63
  # Shutdown
 
91
  - `GET /api/v1/agent-events/stream` - SSE stream for agent events
92
  """,
93
  lifespan=lifespan,
94
+ docs_url="/docs",
95
+ redoc_url="/redoc",
96
  )
97
 
98
 
 
102
  logger.error(f"Unhandled error on {request.method} {request.url.path}: {exc}", exc_info=True)
103
  return JSONResponse(
104
  status_code=500,
105
+ content={"detail": "Internal server error", "error": str(exc)[:200]},
106
  )
107
 
108
 
109
+ # Add CORS middleware with wide origins for demo
110
  app.add_middleware(
111
  CORSMiddleware,
112
+ allow_origins=["*"], # Allow all origins for demo/development
113
  allow_credentials=True,
114
  allow_methods=["*"],
115
  allow_headers=["*"],
 
140
  "status": "healthy",
141
  "service": settings.app_title,
142
  "version": settings.app_version,
143
+ "docs": "/docs",
144
  }
145
 
146
 
 
149
  """Health check endpoint with actual DB verification."""
150
  from app.database import check_db_health
151
  db_ok = await check_db_health()
152
+ status_str = "healthy" if db_ok else "degraded"
153
  return {
154
+ "status": status_str,
155
  "database": "connected" if db_ok else "disconnected",
156
+ "version": settings.app_version,
157
+ }
158
+
159
+
160
+ @app.get("/api/v1/health", tags=["Health"])
161
+ async def api_health():
162
+ """API health check for frontend connectivity tests."""
163
+ from app.database import check_db_health
164
+ db_ok = await check_db_health()
165
+ return {
166
+ "status": "healthy" if db_ok else "degraded",
167
+ "database": "connected" if db_ok else "sqlite_fallback",
168
+ "version": settings.app_version,
169
+ "agents": ["ml_effort", "route_planner", "fairness_manager", "driver_liaison", "final_resolution", "explainability"],
170
+ "langgraph": True,
171
  }
172
 
173