safraeli commited on
Commit
962807d
·
verified ·
1 Parent(s): 537da21

Fix Sentry fail-loud, startup validation, CORS defaults

Browse files
Files changed (1) hide show
  1. backend/api/main.py +33 -2
backend/api/main.py CHANGED
@@ -10,6 +10,7 @@ import logging
10
  import os
11
  import time
12
  from contextlib import asynccontextmanager
 
13
 
14
  from fastapi import FastAPI, Request, Response
15
  from fastapi.middleware.cors import CORSMiddleware
@@ -47,7 +48,10 @@ if _sentry_dsn:
47
  )
48
  log.info("Sentry enabled (env=%s)", os.environ.get("SENTRY_ENV", "production"))
49
  except ImportError:
50
- log.warning("SENTRY_DSN set but sentry-sdk not installed — skipping")
 
 
 
51
 
52
  # ---------------------------------------------------------------------------
53
  # Lifespan — one-time startup / shutdown
@@ -56,11 +60,32 @@ if _sentry_dsn:
56
  _start_time: float = 0.0
57
 
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  @asynccontextmanager
60
  async def lifespan(app: FastAPI):
61
  global _start_time
62
  _start_time = time.time()
63
  log.info("SolarWine API starting (port 7860)")
 
 
 
 
 
 
 
 
64
  yield
65
  log.info("SolarWine API shutting down (uptime=%.0fs)", get_uptime())
66
 
@@ -98,7 +123,13 @@ async def log_requests(request: Request, call_next):
98
 
99
  # -- CORS -------------------------------------------------------------------
100
 
101
- allowed_origins = os.environ.get("ALLOWED_ORIGINS", "http://localhost:3000,http://localhost:5173").split(",")
 
 
 
 
 
 
102
  app.add_middleware(
103
  CORSMiddleware,
104
  allow_origins=[o.strip() for o in allowed_origins],
 
10
  import os
11
  import time
12
  from contextlib import asynccontextmanager
13
+ from pathlib import Path
14
 
15
  from fastapi import FastAPI, Request, Response
16
  from fastapi.middleware.cors import CORSMiddleware
 
48
  )
49
  log.info("Sentry enabled (env=%s)", os.environ.get("SENTRY_ENV", "production"))
50
  except ImportError:
51
+ raise RuntimeError(
52
+ "SENTRY_DSN is set but sentry-sdk is not installed. "
53
+ "Either install it (pip install sentry-sdk[fastapi]) or unset SENTRY_DSN."
54
+ )
55
 
56
  # ---------------------------------------------------------------------------
57
  # Lifespan — one-time startup / shutdown
 
60
  _start_time: float = 0.0
61
 
62
 
63
+ def _check_data_paths():
64
+ """Log warnings for missing data paths at startup."""
65
+ checks = {
66
+ "Data/daily_plan.json": "Control plan endpoint will return 404",
67
+ "Data/energy_predictor_model.pkl": "ML energy prediction will fall back to analytical",
68
+ "Data/ims/ims_merged_15min.csv": "IMS weather cache unavailable — forecast will need live fetch",
69
+ }
70
+ base = Path(__file__).resolve().parent.parent.parent
71
+ for rel_path, msg in checks.items():
72
+ if not (base / rel_path).exists():
73
+ log.warning("Missing %s — %s", rel_path, msg)
74
+
75
+
76
  @asynccontextmanager
77
  async def lifespan(app: FastAPI):
78
  global _start_time
79
  _start_time = time.time()
80
  log.info("SolarWine API starting (port 7860)")
81
+ _check_data_paths()
82
+
83
+ # Log auth status
84
+ if not os.environ.get("JWT_SECRET"):
85
+ log.warning("JWT_SECRET not set — all requests treated as read-only guest")
86
+ if not os.environ.get("ADMIN_PASSWORD"):
87
+ log.warning("ADMIN_PASSWORD not set — login endpoint disabled")
88
+
89
  yield
90
  log.info("SolarWine API shutting down (uptime=%.0fs)", get_uptime())
91
 
 
123
 
124
  # -- CORS -------------------------------------------------------------------
125
 
126
+ _default_origins = ",".join([
127
+ "http://localhost:3000",
128
+ "http://localhost:5173",
129
+ "https://solarwine-api.hf.space",
130
+ "https://solarvine-dashboard.vercel.app",
131
+ ])
132
+ allowed_origins = os.environ.get("ALLOWED_ORIGINS", _default_origins).split(",")
133
  app.add_middleware(
134
  CORSMiddleware,
135
  allow_origins=[o.strip() for o in allowed_origins],