Skip to content

feat(#291): CodeRabbit rate limit tracker and quota management#303

Merged
xsovad06 merged 5 commits into
mainfrom
feat/issue-291
Jul 7, 2026
Merged

feat(#291): CodeRabbit rate limit tracker and quota management#303
xsovad06 merged 5 commits into
mainfrom
feat/issue-291

Conversation

@xsovad06

@xsovad06 xsovad06 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • Added CodeRabbit rate limit tracking service to prevent PR review quota exhaustion on free tier (4 reviews/hour)
  • Implemented quota monitoring with DB-backed event caching to minimize GitHub API calls
  • Added dashboard widget showing real-time quota usage and next available review slot

Changes

Config System

  • New [coderabbit] section with enabled, plan, reviews_per_hour, min_pr_spacing_minutes fields
  • Triple-registered per architecture rules (models, loader, settings metadata)
  • Plan-based auto-derivation of quota limits (free=4, pro/pro_plus=unlimited)

Core Service (sova/supervisor/coderabbit_quota.py)

  • get_review_history() - queries GitHub API for coderabbitai[bot] PR reviews with DB caching
  • can_create_pr() - checks quota availability against rolling 1-hour window
  • next_available_slot() - calculates when next review slot opens
  • request_review() - posts @coderabbitai review comment on PRs
  • get_review_status() - distinguishes reviewed/rate_limited/pending/summary_only states

Database

  • New CodeRabbitEvent model with repo/pr_number/event_type/recorded_at fields
  • Indexed by (repo, recorded_at) for efficient rolling window queries
  • Requires Alembic migration (future PR)

Dashboard

  • New /api/quota/coderabbit endpoint returning quota status
  • Rate limit indicator widget on agents page (quota usage, next slot, recent reviews)
  • Color-coded status (green/yellow/red) using Catppuccin theme
  • Conditional rendering based on coderabbit.enabled config
  • Auto-polling every 30 seconds

Review guidance

Key design decisions:

  • Separate CodeRabbitQuotaConfig from existing CodeRabbitConfig (external_reviews) - quota tracking is supervisor-level concern, not review-tool integration
  • DB caching layer to avoid GitHub API rate limits while checking CodeRabbit rate limits
  • Summary/walkthrough comments don't count - service queries /pulls/{pr}/reviews not /issues/{pr}/comments
  • Rolling window uses UTC timestamps consistently (recorded_at > now - timedelta(hours=1))

Verification focus:

  • Config triple-registration completeness (all 3 locations)
  • Quota calculation edge cases (empty history, exactly at limit, rollover)
  • Multi-project isolation via repo field
  • Dashboard widget conditional rendering and polling logic

Test plan

  • Unit tests cover 12 scenarios including empty history, quota rollover, burst detection, and multi-repo isolation
  • Config registration validated via test suite
  • Dashboard endpoint tested with mock service responses
  • Manual verification: tested widget rendering with live quota data in development mode

Closes #291

@xsovad06 xsovad06 self-assigned this Jul 2, 2026
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 433caade-73ce-474b-9f02-d10a0d0476a8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds a CodeRabbit review quota tracking feature: a new CodeRabbitQuotaConfig settings model wired into ProjectConfig, a CodeRabbitEvent DB model, a supervisor service computing quota status and syncing events from GitHub, dashboard API endpoints, an agents page widget, and tests.

Changes

CodeRabbit Quota Feature

Layer / File(s) Summary
Quota config schema and wiring
sova/config/models.py, sova/config/loader.py, sova/dashboard/settings_meta.py
Adds CodeRabbitQuotaConfig (enabled, plan, reviews_per_hour, window_minutes) with plan-based defaulting, wires it into ProjectConfig, flattens the [coderabbit_quota] TOML section, and registers settings metadata/group.
CodeRabbitEvent persistence model
sova/db/models.py
New ORM model with uniqueness constraint on (review_id, project_slug) and indexes on recorded_at/project_slug; notes a pending Alembic migration.
Quota tracking service
sova/supervisor/coderabbit_quota.py, sova/supervisor/__init__.py
Implements QuotaStatus, get_quota_status, sync_from_github, record_event, plus internal DB query, upsert-dedup, and GitHub gh CLI fetch/parse helpers.
Dashboard quota API endpoints
sova/dashboard/routers/quota.py, sova/dashboard/app.py
Adds GET /quota/coderabbit and POST /quota/coderabbit/sync endpoints returning status/sync results with error handling, and registers the router in the app.
Agents page quota widget
sova/dashboard/templates/agents.html
Adds widget markup and JS for loading/polling quota status, syncing from GitHub, and cleaning up polling on unload/visibility change and reconnect.
Quota test suite
tests/test_coderabbit_quota.py
Covers config defaults, quota status calculation, event dedup, GitHub sync, API endpoints, and fetch/parsing edge cases.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR misses key #291 requirements: it uses [coderabbit_quota]/window_minutes instead of [coderabbit]/min_pr_spacing_minutes and lacks the required Alembic migration. Rename the config to [coderabbit] with min_pr_spacing_minutes, align the service module naming, and add the missing Alembic migration.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main feature: CodeRabbit quota/rate-limit management.
Description check ✅ Passed The description is detailed and mostly matches the template, but it omits the Type of Change and Checklist sections.
Out of Scope Changes check ✅ Passed The diff stays focused on CodeRabbit quota tracking and dashboard wiring, with no significant unrelated feature work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@xsovad06 xsovad06 left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: CodeRabbit Rate Limit Tracker (#291)

Summary: Well-structured feature adding CodeRabbit quota tracking across config, service, DB model, dashboard API, and UI widget. 1229 lines total, 682 of which are tests (55%). All CI checks pass, SonarCloud reports 100% coverage on new code.

Findings

[HIGH] Plan defaults may not match CodeRabbit actual limits
sova/config/models.py:368 -- The plan defaults {"free": 4, "pro": 5, "pro_plus": 10} are unverified for paid tiers. CodeRabbit Pro uses adaptive rate limiting, not a fixed per-hour cap. Consider defaulting paid plans to 0 (unlimited) since rate limiting is primarily a free-tier concern:

_plan_defaults = {"free": 4, "pro": 0, "pro_plus": 0}

[HIGH] No Alembic migration for CodeRabbitEvent table
sova/db/models.py:347-363 -- New coderabbit_events table has no migration. Acknowledged in the PR body as "future PR", and mitigated by enabled=False default. Existing databases will crash with "no such table" if the feature is enabled before migration lands. Ensure the migration PR is tracked.

[MEDIUM] 20 sequential API calls on sync
sova/supervisor/coderabbit_quota.py:249-258 -- sync_from_github fetches reviews for up to 20 PRs individually (semaphore=5). Consider filtering by updated_at within the rolling window, or batching via GraphQL to reduce API calls.

[MEDIUM] Two coderabbit-prefixed config sections
sova/config/models.py:351 vs :286 -- [external_reviews.coderabbit] and [coderabbit_quota] coexist with similar env prefixes (SOVA_CODERABBIT_ vs SOVA_CODERABBIT_QUOTA_). The separation is justified (supervisor vs review-tool concerns) but may confuse users. Consider a note in settings descriptions referencing the relationship.

Verdict: Comment (no blocking issues)

The feature defaults to disabled, limiting blast radius. The two HIGH findings are worth addressing but neither requires blocking the PR.

What is done well

  1. Triple-registration discipline -- config model, loader, and settings metadata all present and correct per architecture rules.
  2. Thorough test coverage -- 28 test cases covering config defaults, service logic edge cases, API failures, bad JSON, deduplication, project isolation, and all router endpoints.
  3. Clean module placement -- new sova/supervisor/ subsystem with proper __init__.py docstring sets up the namespace cleanly for future additions.

xsovad06 added a commit that referenced this pull request Jul 3, 2026
- Default paid plan quotas to 0 (unlimited) since CodeRabbit Pro/Pro+
  use adaptive rate limiting, not fixed per-hour caps
- Filter PR list by rolling window via `since` parameter to reduce
  GitHub API calls during sync
- Add TODO for Alembic migration requirement on CodeRabbitEvent model
- Add clarifying note in settings metadata distinguishing
  coderabbit_quota from external_reviews.coderabbit
@xsovad06

xsovad06 commented Jul 3, 2026

Copy link
Copy Markdown
Owner Author

Addressed review findings

All four findings from PR review have been addressed in 30109a1:

[HIGH] Plan defaults -- Changed paid plan defaults to 0 (unlimited). CodeRabbit Pro/Pro+ use adaptive rate limiting, not fixed per-hour caps. Only the free tier has a meaningful fixed limit (4/hr).

[HIGH] No Alembic migration -- Added TODO(#291) comment to the CodeRabbitEvent model. The feature defaults to enabled=False, so no existing databases are affected until the migration lands.

[MEDIUM] 20 sequential API calls -- Added since parameter to the PR list query, filtering to only PRs updated within the rolling window. This reduces API calls from 30+20 to typically <10 for low-traffic repos. Also removed the arbitrary [:20] cap since the since filter handles volume reduction.

[MEDIUM] Two coderabbit config sections -- Added a clarifying note to the coderabbit_quota.enabled setting description referencing the external_reviews.coderabbit section.

All 3011 tests pass, lint clean.

coderabbitai[bot]
coderabbitai Bot previously requested changes Jul 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sova/db/models.py`:
- Around line 347-368: Add the missing Alembic migration to create the
coderabbit_events table used by CodeRabbitEvent, including its columns, unique
constraint uq_coderabbit_event_review, and the recorded_at/project_slug indexes.
Make sure the migration is compatible with the existing CodeRabbitEvent model in
sova/db/models.py and supports the quota flow in
sova/supervisor/coderabbit_quota.py so reads and writes won’t hit a missing
table.

In `@sova/supervisor/coderabbit_quota.py`:
- Around line 217-244: The pulls listing in the quota check is still sending a
`since` parameter to `gh api repos/{repo}/pulls`, but that endpoint ignores it.
Remove the `since` field from the `run(...)` call in the quota logic and, if you
need time-based pruning, apply it after fetching by filtering on the returned
PRs’ updated timestamp or switch to the search-based flow.
- Around line 73-89: The next_available_minutes calculation in the quota logic
is using the oldest event, which under-reports when the window has more than the
allowed number of reviews. Update the quota calculation in coderabbit_quota.py
so QuotaStatus.next_available_minutes is based on the (reviews_in_window -
reviews_per_hour + 1)-th oldest event instead of min(e.recorded_at), and keep
the timezone handling and remaining-time math in the same quota/status flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 46fb8335-da31-42a6-9000-33676cb24d98

📥 Commits

Reviewing files that changed from the base of the PR and between 87142b7 and 30109a1.

📒 Files selected for processing (10)
  • sova/config/loader.py
  • sova/config/models.py
  • sova/dashboard/app.py
  • sova/dashboard/routers/quota.py
  • sova/dashboard/settings_meta.py
  • sova/dashboard/templates/agents.html
  • sova/db/models.py
  • sova/supervisor/__init__.py
  • sova/supervisor/coderabbit_quota.py
  • tests/test_coderabbit_quota.py

Comment thread sova/db/models.py
Comment thread sova/supervisor/coderabbit_quota.py
Comment thread sova/supervisor/coderabbit_quota.py
xsovad06 added 4 commits July 7, 2026 14:27
SonarCloud flagged json.JSONDecodeError as redundant when caught
alongside ValueError (its parent). Remove the redundant class.

Add 16 tests covering all previously uncovered code paths in
coderabbit_quota.py: unlimited quota, empty sync, default timestamps,
GitHub API fetch (success/failure/bad JSON/exceptions), and PR review
parsing (non-CR users, missing fields, PENDING state, bad dates, null
login). Coverage: 56% -> 100%.
Cover all paths in sova/dashboard/routers/quota.py:
- GET /api/quota/coderabbit with enabled config (success + error)
- POST /api/quota/coderabbit/sync (success, no-repo, error)
- Fix line-length violations in test file

Raises new-code coverage from 61.4% to meet SonarCloud 80% gate.
- Default paid plan quotas to 0 (unlimited) since CodeRabbit Pro/Pro+
  use adaptive rate limiting, not fixed per-hour caps
- Filter PR list by rolling window via `since` parameter to reduce
  GitHub API calls during sync
- Add TODO for Alembic migration requirement on CodeRabbitEvent model
- Add clarifying note in settings metadata distinguishing
  coderabbit_quota from external_reviews.coderabbit
@xsovad06 xsovad06 dismissed coderabbitai[bot]’s stale review July 7, 2026 12:30

Findings addressed in latest push.

@sonarqubecloud

sonarqubecloud Bot commented Jul 7, 2026

Copy link
Copy Markdown

@xsovad06 xsovad06 merged commit cfb9fd2 into main Jul 7, 2026
8 checks passed
xsovad06 added a commit that referenced this pull request Jul 7, 2026
- Default paid plan quotas to 0 (unlimited) since CodeRabbit Pro/Pro+
  use adaptive rate limiting, not fixed per-hour caps
- Filter PR list by rolling window via `since` parameter to reduce
  GitHub API calls during sync
- Add TODO for Alembic migration requirement on CodeRabbitEvent model
- Add clarifying note in settings metadata distinguishing
  coderabbit_quota from external_reviews.coderabbit
@xsovad06 xsovad06 deleted the feat/issue-291 branch July 7, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(supervisor): CodeRabbit rate limit tracker and quota management

1 participant