Skip to content

Get endpoint makes O(n) synchronous API calls to Codeforces — will flood and get rate-limited #214

Description

@amaydixit11

Bug Description

The GET endpoint for Codeforces leaderboard makes 2 synchronous HTTP API calls per registered user for every single request, causing massive API flooding.

Affected File

api/leaderboard/views.py:302-319 (CodeforcesLeaderboard.get())

Problem

def get(self, request):
    cf_users = codeforcesUser.objects.all()

    for user in cf_users:
        user_data = self.get_codeforces_data(user.username)               # HTTP call #1
        user_submission_stats = self.get_codeforces_submission_stats(...) # HTTP call #2
        if user_submission_stats:
            user.total_solved = user_submission_stats["total_solved"]
            user.total_submissions = user_submission_stats["total_submissions"]
        if user_data:
            user.rating = user_data["rating"]
            ...
        user.save()

    serializer = CF_Serializer(cf_users, many=True)
    return Response(serializer.data)

With 200 registered users, a single GET request makes 400 synchronous HTTP calls to codeforces.com/api/. This will:

  1. Block the request for 30+ seconds (each call takes ~100-500ms)
  2. Get the server IP rate-limited by Codeforces (API limit: ~1 call/second, ~1000/hour per IP)
  3. Make all users unable to load the leaderboard if Codeforces blocks the IP
  4. Consume excessive server memory loading all users into memory

Steps to Reproduce

  1. Register 100+ users on the leaderboard
  2. Call GET /api/github/codeforces/
  3. Observe the request timing out and Codeforces returning 429/503 errors

Proposed Fix

Return cached data immediately. Use the existing Celery beat scheduled task (cf_update_db_task) for background data refresh, which is already configured in settings.py:262-264.

def get(self, request):
    # Return cached data — let Celery handle async refresh
    cf_users = codeforcesUser.objects.all()
    serializer = CF_Serializer(cf_users, many=True)
    return Response(serializer.data)

If a specific user's data needs refreshing on demand, add a separate endpoint like GET /api/github/codeforces/refresh/{username}/ that triggers an async task.

Severity

HIGH — Will cause production outages with even moderate user counts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    advancedComplex issues requiring experienced contributorsbugbug d73a4a 'Something isn't working'securitysecurity d73a4a 'Security vulnerability'

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions