safraeli commited on
Commit
43dbcc2
·
verified ·
1 Parent(s): 609f122

Add background IMS refresh scheduler (every 6h)

Browse files
Files changed (1) hide show
  1. backend/api/main.py +43 -1
backend/api/main.py CHANGED
@@ -74,6 +74,43 @@ def _check_data_paths():
74
  log.warning("Missing %s — %s", rel_path, msg)
75
 
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  @asynccontextmanager
78
  async def lifespan(app: FastAPI):
79
  global _start_time
@@ -87,7 +124,12 @@ async def lifespan(app: FastAPI):
87
  if not os.environ.get("ADMIN_PASSWORD"):
88
  log.warning("ADMIN_PASSWORD not set — login endpoint disabled")
89
 
 
 
 
 
90
  yield
 
91
  log.info("SolarWine API shutting down (uptime=%.0fs)", get_uptime())
92
 
93
 
@@ -138,7 +180,7 @@ _default_origins = ",".join([
138
  "http://localhost:3000",
139
  "http://localhost:5173",
140
  "https://solarwine-api.hf.space",
141
- "https://solarvine-dashboard.vercel.app",
142
  ])
143
  allowed_origins = os.environ.get("ALLOWED_ORIGINS", _default_origins).split(",")
144
  app.add_middleware(
 
74
  log.warning("Missing %s — %s", rel_path, msg)
75
 
76
 
77
+ async def _ims_refresh_loop(interval_sec: int = 6 * 3600):
78
+ """Background loop: refresh the IMS weather cache every `interval_sec` seconds.
79
+
80
+ Fetches the last 14 days of IMS data, overwrites the local CSV cache,
81
+ and invalidates the in-memory WeatherService cache so the next request
82
+ picks up fresh data.
83
+ """
84
+ import asyncio
85
+ await asyncio.sleep(10) # let the server finish starting
86
+ while True:
87
+ try:
88
+ from datetime import date, timedelta
89
+ from src.data.ims_client import IMSClient
90
+ end = date.today()
91
+ start = end - timedelta(days=14)
92
+ client = IMSClient()
93
+ loop = asyncio.get_event_loop()
94
+ df = await loop.run_in_executor(
95
+ None,
96
+ lambda: client.fetch_and_cache(
97
+ str(start), str(end), chunk_days=14
98
+ ),
99
+ )
100
+ rows = len(df) if df is not None and not df.empty else 0
101
+ log.info("IMS cache refreshed: %d rows (%s → %s)", rows, start, end)
102
+ # Invalidate WeatherService in-memory cache so next request uses fresh data
103
+ try:
104
+ from backend.api.deps import get_datahub
105
+ hub = get_datahub()
106
+ hub.weather._df_cache._store.clear()
107
+ except Exception:
108
+ pass
109
+ except Exception as exc:
110
+ log.error("IMS refresh failed: %s", exc)
111
+ await asyncio.sleep(interval_sec)
112
+
113
+
114
  @asynccontextmanager
115
  async def lifespan(app: FastAPI):
116
  global _start_time
 
124
  if not os.environ.get("ADMIN_PASSWORD"):
125
  log.warning("ADMIN_PASSWORD not set — login endpoint disabled")
126
 
127
+ # Start background IMS data refresh (every 6 hours)
128
+ import asyncio
129
+ ims_task = asyncio.create_task(_ims_refresh_loop())
130
+
131
  yield
132
+ ims_task.cancel()
133
  log.info("SolarWine API shutting down (uptime=%.0fs)", get_uptime())
134
 
135
 
 
180
  "http://localhost:3000",
181
  "http://localhost:5173",
182
  "https://solarwine-api.hf.space",
183
+ "https://solarwine.pages.dev",
184
  ])
185
  allowed_origins = os.environ.get("ALLOWED_ORIGINS", _default_origins).split(",")
186
  app.add_middleware(