Skip to content

feat: analysis runs for all fetched issues in parallel with no concurrency limit β€” for large repos (500+ issues), this fires hundreds of simultaneous OpenRouter API requests and exhausts rate limits within seconds, causing cascading 429 errorsΒ #89

Description

@divyanshim27

πŸ› Problem Statement

IssueScope fetches issues and then performs AI analysis on each one. The README states: "Fetches issue details and performs AI analysis in parallel for high throughput." However, unbounded parallelism is the opposite of high throughput when the downstream API has rate limits.

OpenRouter free-tier rate limits are typically 10-20 requests/minute per key. For a repo with 100 open issues, IssueScope fires 100 concurrent requests, hitting the rate limit within the first second. React Query retries with exponential backoff β€” but all 100 are retrying simultaneously, creating a thundering herd that ensures the rate limit is hit on every retry wave too.

Result: All 100 issues show "Analysis Failed" with error 429 Too Many Requests. The tool is functionally unusable on any repo with more than ~15 issues.

Proposed Fix

Implement a concurrency-limited analysis queue using p-limit:

// src/hooks/useAnalysis.ts
import pLimit from 'p-limit'; // add to package.json

const CONCURRENT_ANALYSIS_LIMIT = 3; // Conservative β€” respects free-tier limits

export const useAnalyzeIssues = (issues: GitHubIssue[], apiKey: string) => {
  return useQuery({
    queryKey: ['analysis', issues.map(i => i.number)],
    queryFn: async () => {
      const limit = pLimit(CONCURRENT_ANALYSIS_LIMIT);
      const results = await Promise.all(
        issues.map(issue =>
          limit(async () => {
            try {
              return await analyzeIssue(issue, apiKey);
            } catch (err) {
              if (isRateLimitError(err)) {
                // Exponential backoff with jitter before retrying
                await sleep(2000 + Math.random() * 1000);
                return analyzeIssue(issue, apiKey);
              }
              return { issueNumber: issue.number, error: 'Analysis failed', score: 0 };
            }
          })
        )
      );
      return results;
    },
    enabled: issues.length > 0 && !!apiKey,
  });
};

const isRateLimitError = (err: unknown) =>
  err instanceof Error && err.message.includes('429');

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

Also expose a settings control in the UI for users with paid OpenRouter plans to increase the concurrency limit.

Files to Modify

File Change
package.json Add p-limit dependency
src/hooks/useAnalysis.ts Wrap analysis calls with pLimit(3)
src/components/SettingsPanel.tsx Add "Concurrency" slider (1–10) for advanced users
src/store/settingsStore.ts Persist concurrency preference in Zustand
README.md Document rate limit behaviour and recommended settings

Suggested labels: bug, performance, api, ux

I would like to work on this. Could you please assign it to me?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions