Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions backend/routers/utility.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import JSONResponse
from fastapi import APIRouter, Depends, HTTPException, Query, Response
from sqlalchemy.orm import Session
from sqlalchemy import func, case
from datetime import datetime, timezone
import logging
import json

from backend.database import get_db
from backend.models import Issue
Expand Down Expand Up @@ -51,7 +51,7 @@ def health():
def get_stats(db: Session = Depends(get_db)):
cached_stats = recent_issues_cache.get("stats")
if cached_stats:
return JSONResponse(content=cached_stats)
return Response(content=cached_stats, media_type="application/json")

Comment thread
RohanExploit marked this conversation as resolved.
# Optimized: Single aggregate query for both category breakdowns and system-wide totals
# This eliminates a redundant database roundtrip
Expand Down Expand Up @@ -84,9 +84,10 @@ def get_stats(db: Session = Depends(get_db)):
)

data = response.model_dump(mode='json')
recent_issues_cache.set(data, "stats")
json_data = json.dumps(data)
recent_issues_cache.set(json_data, "stats")

return response
return Response(content=json_data, media_type="application/json")

@router.get("/ml-status", response_model=MLStatusResponse)
async def ml_status():
Expand Down Expand Up @@ -116,7 +117,7 @@ def get_leaderboard(db: Session = Depends(get_db)):
cache_key = "leaderboard"
cached_data = recent_issues_cache.get(cache_key)
if cached_data:
return JSONResponse(content=cached_data)
return Response(content=cached_data, media_type="application/json")

# Group by user_email, count issues, sum upvotes
# Optimization: Only select needed columns and use aggregation
Expand Down Expand Up @@ -149,10 +150,11 @@ def get_leaderboard(db: Session = Depends(get_db)):
).model_dump(mode='json'))

response_data = {"leaderboard": leaderboard_data}
json_data = json.dumps(response_data)
# Cache for 5 minutes to reduce DB load on frequent hits
recent_issues_cache.set(response_data, cache_key)
recent_issues_cache.set(json_data, cache_key)

return response_data
return Response(content=json_data, media_type="application/json")


@router.get("/mh/rep-contacts")
Expand Down
26 changes: 26 additions & 0 deletions backend/tests/benchmark_serialization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import time
import json
from fastapi import Response
from fastapi.responses import JSONResponse

data = {"leaderboard": [{"user_email": "abc@def.com", "reports_count": 10, "total_upvotes": 50, "rank": 1} for _ in range(100)]}
json_data = json.dumps(data)

def test_jsonresponse():
start = time.perf_counter()
for _ in range(10000):
Comment thread
RohanExploit marked this conversation as resolved.
# JSONResponse internally calls json.dumps
resp = JSONResponse(content=data)
_ = resp.body
return time.perf_counter() - start

def test_rawresponse():
start = time.perf_counter()
for _ in range(10000):
resp = Response(content=json_data, media_type="application/json")
Comment thread
RohanExploit marked this conversation as resolved.
_ = resp.body
return time.perf_counter() - start

if __name__ == "__main__":
print(f"JSONResponse: {test_jsonresponse():.4f}s")
print(f"Response with pre-serialized JSON: {test_rawresponse():.4f}s")
Loading