CodeCommunity commited on
Commit
2340fec
·
verified ·
1 Parent(s): fcb8ccd

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +51 -12
app/main.py CHANGED
@@ -113,14 +113,40 @@ async def classify_file(request: FileRequest):
113
  async def review_batch_code(request: BatchReviewRequest):
114
  try:
115
  loop = asyncio.get_event_loop()
116
- with ThreadPoolExecutor() as executor:
117
- reviews = await loop.run_in_executor(
118
- executor, reviewer.service.review_batch_code, request.files
119
- )
120
- return {"results": reviews}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  except Exception as e:
122
- if "429" in str(e):
123
- raise HTTPException(status_code=429, detail="AI Quota Exceeded")
124
  traceback.print_exc()
125
  raise HTTPException(status_code=500, detail=str(e))
126
 
@@ -128,17 +154,30 @@ async def review_batch_code(request: BatchReviewRequest):
128
  async def get_dashboard_stats(request: BatchReviewRequest):
129
  try:
130
  loop = asyncio.get_event_loop()
131
- with ThreadPoolExecutor() as executor:
132
- raw_reviews = await loop.run_in_executor(
133
- executor, reviewer.service.review_batch_code, request.files
134
- )
 
 
 
 
 
 
 
 
135
 
136
  total_vulns = 0
137
  maint_scores = []
138
  found_apis = set()
139
  api_regex = re.compile(r'(?:get|post|put|delete|patch)\([\'"]\/(.*?)[\'"]', re.IGNORECASE)
140
 
 
141
  for i, review in enumerate(raw_reviews):
 
 
 
 
142
  vulns = review.get("vulnerabilities", [])
143
  total_vulns += len(vulns)
144
  m_score = review.get("metrics", {}).get("maintainability", 8.0)
@@ -166,7 +205,7 @@ async def get_dashboard_stats(request: BatchReviewRequest):
166
  except Exception as e:
167
  if "429" in str(e):
168
  raise HTTPException(status_code=429, detail="Quota exceeded")
169
- logger.error(f"Dashboard stats failed: {e}")
170
  raise HTTPException(status_code=500, detail="Failed to sync dashboard metrics")
171
 
172
  @app.post("/analyze-file")
 
113
  async def review_batch_code(request: BatchReviewRequest):
114
  try:
115
  loop = asyncio.get_event_loop()
116
+
117
+ # Helper function to process one file at a time, WITH the fix to unwrap the list
118
+ def process_single_file(file_req):
119
+ return reviewer.service.review_batch_code([file_req])
120
+
121
+ # Spin up a ThreadPoolExecutor with up to 15 concurrent workers
122
+ with ThreadPoolExecutor(max_workers=15) as executor:
123
+ # Create a concurrent task for every file in the request
124
+ tasks = [
125
+ loop.run_in_executor(executor, process_single_file, f)
126
+ for f in request.files
127
+ ]
128
+
129
+ # asyncio.gather fires them all off at the exact same time
130
+ raw_reviews = await asyncio.gather(*tasks, return_exceptions=True)
131
+
132
+ # Clean up the results and handle any individual file failures gracefully
133
+ valid_reviews = []
134
+ for i, result in enumerate(raw_reviews):
135
+ if isinstance(result, Exception):
136
+ # If we hit a rate limit, bubble it up immediately
137
+ if "429" in str(result):
138
+ raise HTTPException(status_code=429, detail="AI Quota Exceeded")
139
+
140
+ # Otherwise, log the specific file error but don't crash the whole batch
141
+ logger.error(f"Failed to analyze {request.files[i].fileName}: {result}")
142
+ else:
143
+ valid_reviews.append(result)
144
+
145
+ return {"results": valid_reviews}
146
+
147
  except Exception as e:
148
+ if isinstance(e, HTTPException):
149
+ raise e
150
  traceback.print_exc()
151
  raise HTTPException(status_code=500, detail=str(e))
152
 
 
154
  async def get_dashboard_stats(request: BatchReviewRequest):
155
  try:
156
  loop = asyncio.get_event_loop()
157
+
158
+ # 1. Use the same parallel helper for blazing fast stats!
159
+ def process_single_file(file_req):
160
+ return reviewer.service.review_batch_code([file_req])
161
+
162
+ # 2. Run all files concurrently
163
+ with ThreadPoolExecutor(max_workers=15) as executor:
164
+ tasks = [
165
+ loop.run_in_executor(executor, process_single_file, f)
166
+ for f in request.files
167
+ ]
168
+ raw_reviews = await asyncio.gather(*tasks, return_exceptions=True)
169
 
170
  total_vulns = 0
171
  maint_scores = []
172
  found_apis = set()
173
  api_regex = re.compile(r'(?:get|post|put|delete|patch)\([\'"]\/(.*?)[\'"]', re.IGNORECASE)
174
 
175
+ # 3. Process the results, ignoring any parallel tasks that failed
176
  for i, review in enumerate(raw_reviews):
177
+ if isinstance(review, Exception):
178
+ logger.error(f"Skipping stats for {request.files[i].fileName} due to error: {review}")
179
+ continue # Skip failed files so the dashboard doesn't crash
180
+
181
  vulns = review.get("vulnerabilities", [])
182
  total_vulns += len(vulns)
183
  m_score = review.get("metrics", {}).get("maintainability", 8.0)
 
205
  except Exception as e:
206
  if "429" in str(e):
207
  raise HTTPException(status_code=429, detail="Quota exceeded")
208
+ logger.error(f"Dashboard stats failed: {traceback.format_exc()}")
209
  raise HTTPException(status_code=500, detail="Failed to sync dashboard metrics")
210
 
211
  @app.post("/analyze-file")