abhisheksan commited on
Commit
9c81152
·
verified ·
1 Parent(s): 0873402

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -76
app.py CHANGED
@@ -7,7 +7,6 @@ from dotenv import load_dotenv
7
  from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, status
8
  from fastapi.middleware.cors import CORSMiddleware
9
  from loguru import logger
10
- from pydantic import BaseModel
11
 
12
  from analysis_service import AnalysisService
13
  from twitter_service import RssTwitterService
@@ -21,6 +20,9 @@ load_dotenv()
21
  os.makedirs("logs", exist_ok=True)
22
  logger.add("logs/app.log", rotation="500 MB", level=os.getenv("LOG_LEVEL", "INFO"))
23
 
 
 
 
24
  # Create FastAPI application
25
  app = FastAPI(
26
  title="WesternFront API",
@@ -45,14 +47,6 @@ analysis_service = AnalysisService()
45
  latest_analysis: Optional[ConflictAnalysis] = None
46
  last_update_time: Optional[datetime] = None
47
 
48
- # Define model for RSS feed registration
49
- class RssFeedRegistration(BaseModel):
50
- twitter_handle: str
51
- rss_url: str
52
-
53
- class RssFeedBatch(BaseModel):
54
- feeds: Dict[str, str]
55
-
56
 
57
  async def get_twitter_service() -> RssTwitterService:
58
  """Dependency to get the Twitter service."""
@@ -67,39 +61,35 @@ async def get_analysis_service() -> AnalysisService:
67
  @app.on_event("startup")
68
  async def startup_event():
69
  """Initialize services on startup."""
70
- logger.info("Starting up WesternFront API")
71
-
72
- # Initialize services
73
- twitter_initialized = await twitter_service.initialize()
74
- if not twitter_initialized:
75
- logger.warning("Twitter service initialization failed. Some features may not work.")
76
-
77
- # Set analysis service's twitter service reference
78
- analysis_service.twitter_service = twitter_service
79
-
80
- # Initialize Gemini AI service
81
- gemini_initialized = analysis_service.initialize()
82
- if not gemini_initialized:
83
- logger.warning("Gemini AI initialization failed. Analysis features may not work.")
84
-
85
- # Load RSS feeds from environment variable if available
86
- rss_feeds_env = os.getenv("RSS_FEEDS")
87
- if rss_feeds_env:
88
- try:
89
- import json
90
- feeds = json.loads(rss_feeds_env)
91
- if isinstance(feeds, dict):
92
- twitter_service.register_rss_feed_batch(feeds)
93
- logger.info(f"Loaded {len(feeds)} RSS feeds from environment variables")
94
- except Exception as e:
95
- logger.error(f"Failed to load RSS feeds from environment variables: {str(e)}")
96
 
97
- # Schedule first update
98
- background_tasks = BackgroundTasks()
99
- background_tasks.add_task(update_analysis_task)
100
 
101
- # Set up periodic update task
102
- asyncio.create_task(periodic_update())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
 
105
  @app.on_event("shutdown")
@@ -162,10 +152,19 @@ async def root():
162
  return {
163
  "name": "WesternFront API",
164
  "description": "AI-powered conflict tracker for India-Pakistan tensions",
165
- "version": "1.1.0"
 
166
  }
167
 
168
 
 
 
 
 
 
 
 
 
169
  @app.get("/health", response_model=HealthCheck)
170
  async def health_check():
171
  """Health check endpoint."""
@@ -173,7 +172,7 @@ async def health_check():
173
  gemini_initialized = analysis_service.model is not None
174
 
175
  return HealthCheck(
176
- status="healthy",
177
  version="1.1.0",
178
  timestamp=datetime.now(),
179
  last_update=last_update_time,
@@ -196,21 +195,18 @@ async def get_latest_analysis():
196
 
197
 
198
  @app.post("/analysis/update", response_model=Dict)
199
- async def trigger_update(
200
- request: UpdateRequest,
201
- background_tasks: BackgroundTasks
202
- ):
203
  """Trigger an analysis update."""
204
  if request.force:
205
  # Clear cache to force fresh tweets
206
  twitter_service.in_memory_cache.clear()
207
-
208
- # Add update task to background tasks
209
- background_tasks.add_task(update_analysis_task, "manual")
210
 
211
  return {
212
  "message": "Analysis update triggered",
213
- "timestamp": datetime.now(),
214
  "force_refresh": request.force
215
  }
216
 
@@ -263,32 +259,6 @@ async def get_tension_levels():
263
  return [level.value for level in TensionLevel]
264
 
265
 
266
- @app.post("/rss-feed", response_model=Dict)
267
- async def register_rss_feed(
268
- feed: RssFeedRegistration,
269
- twitter: RssTwitterService = Depends(get_twitter_service)
270
- ):
271
- """Register an RSS feed for a Twitter handle."""
272
- twitter.register_rss_feed(feed.twitter_handle, feed.rss_url)
273
- return {
274
- "message": f"RSS feed registered for {feed.twitter_handle}",
275
- "twitter_handle": feed.twitter_handle
276
- }
277
-
278
-
279
- @app.post("/rss-feeds", response_model=Dict)
280
- async def register_rss_feeds(
281
- feeds: RssFeedBatch,
282
- twitter: RssTwitterService = Depends(get_twitter_service)
283
- ):
284
- """Register multiple RSS feeds at once."""
285
- twitter.register_rss_feed_batch(feeds.feeds)
286
- return {
287
- "message": "RSS feeds registered",
288
- "count": len(feeds.feeds)
289
- }
290
-
291
-
292
  @app.get("/rss-feeds", response_model=Dict[str, str])
293
  async def get_registered_rss_feeds(
294
  twitter: RssTwitterService = Depends(get_twitter_service)
 
7
  from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, status
8
  from fastapi.middleware.cors import CORSMiddleware
9
  from loguru import logger
 
10
 
11
  from analysis_service import AnalysisService
12
  from twitter_service import RssTwitterService
 
20
  os.makedirs("logs", exist_ok=True)
21
  logger.add("logs/app.log", rotation="500 MB", level=os.getenv("LOG_LEVEL", "INFO"))
22
 
23
+ # Global readiness flag
24
+ app_ready = False
25
+
26
  # Create FastAPI application
27
  app = FastAPI(
28
  title="WesternFront API",
 
47
  latest_analysis: Optional[ConflictAnalysis] = None
48
  last_update_time: Optional[datetime] = None
49
 
 
 
 
 
 
 
 
 
50
 
51
  async def get_twitter_service() -> RssTwitterService:
52
  """Dependency to get the Twitter service."""
 
61
  @app.on_event("startup")
62
  async def startup_event():
63
  """Initialize services on startup."""
64
+ global app_ready
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ logger.info("Starting up WesternFront API")
 
 
67
 
68
+ try:
69
+ # Initialize Twitter service
70
+ twitter_initialized = await twitter_service.initialize()
71
+ if not twitter_initialized:
72
+ logger.warning("Twitter service initialization failed. Some features may not work.")
73
+
74
+ # Initialize Gemini AI service
75
+ analysis_service.initialize()
76
+
77
+ # Set analysis service's twitter service reference
78
+ analysis_service.twitter_service = twitter_service
79
+
80
+ # Schedule first update in background
81
+ asyncio.create_task(update_analysis_task("startup"))
82
+
83
+ # Set up periodic update task
84
+ asyncio.create_task(periodic_update())
85
+
86
+ # Mark application as ready to accept requests
87
+ app_ready = True
88
+ logger.info("Application ready to accept requests")
89
+
90
+ except Exception as e:
91
+ logger.error(f"Error during startup: {e}")
92
+ app_ready = False # Keep app in not-ready state if startup fails
93
 
94
 
95
  @app.on_event("shutdown")
 
152
  return {
153
  "name": "WesternFront API",
154
  "description": "AI-powered conflict tracker for India-Pakistan tensions",
155
+ "version": "1.1.0",
156
+ "status": "ready" if app_ready else "initializing"
157
  }
158
 
159
 
160
+ @app.get("/ready")
161
+ async def readiness_check():
162
+ """Readiness check endpoint for probes and monitoring."""
163
+ if not app_ready:
164
+ raise HTTPException(status_code=503, detail="Application is starting up")
165
+ return {"status": "ready", "timestamp": datetime.now().isoformat()}
166
+
167
+
168
  @app.get("/health", response_model=HealthCheck)
169
  async def health_check():
170
  """Health check endpoint."""
 
172
  gemini_initialized = analysis_service.model is not None
173
 
174
  return HealthCheck(
175
+ status="healthy" if app_ready else "initializing",
176
  version="1.1.0",
177
  timestamp=datetime.now(),
178
  last_update=last_update_time,
 
195
 
196
 
197
  @app.post("/analysis/update", response_model=Dict)
198
+ async def trigger_update(request: UpdateRequest):
 
 
 
199
  """Trigger an analysis update."""
200
  if request.force:
201
  # Clear cache to force fresh tweets
202
  twitter_service.in_memory_cache.clear()
203
+
204
+ # Start update in background
205
+ asyncio.create_task(update_analysis_task("manual"))
206
 
207
  return {
208
  "message": "Analysis update triggered",
209
+ "timestamp": datetime.now().isoformat(),
210
  "force_refresh": request.force
211
  }
212
 
 
259
  return [level.value for level in TensionLevel]
260
 
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  @app.get("/rss-feeds", response_model=Dict[str, str])
263
  async def get_registered_rss_feeds(
264
  twitter: RssTwitterService = Depends(get_twitter_service)