feat(#294): PR creation throttle for CodeRabbit rate limit compliance#306
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds a DB-backed PR creation queue for quota-enabled runs, routes CreatePRStep through throttled or immediate creation, starts queue workers in dashboard lifespan, exposes queue status in the API, and adds coverage for queue lifecycle and integration paths. ChangesPR Creation Throttling
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 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/core/steps/create_pr.py`:
- Around line 117-118: The nested _session_factory in create_pr.py is missing a
return type annotation, which violates the type-hinting requirement and triggers
ANN202. Add an explicit async return annotation to _session_factory using
AsyncSession, and import AsyncSession from sqlalchemy.ext.asyncio if it is not
already available, while leaving the get_session(project_dir=ctx.project_dir)
call unchanged.
- Around line 64-67: The PR creation flow in create_pr.py is incorrectly
choosing the throttled path in multi-project deployments, which can leave
`poll_until_created()` waiting until timeout because `process_queue_loop()` is
only active for single-project apps. Update the `CreatePR` logic in `_create_pr`
to skip `_create_pr_throttled()` when running in multi-project mode, or ensure
the queue processor is started for that deployment type, while keeping
`_create_pr_immediate()` as the fallback path.
In `@sova/dashboard/app.py`:
- Around line 229-230: The async helper _pr_session_factory in app.py is missing
a return type annotation, so update its function signature to be fully
type-hinted as required by the coding guidelines and ANN202. Add the appropriate
return annotation for the session object returned by
get_session(project_dir=resolved), and keep the change localized to
_pr_session_factory so the signature is explicit and consistent with the rest of
the typed code.
- Around line 219-238: The PR throttle worker is only started in the
single-project path, so throttled PRs in multi-project runs never get consumed.
Update the startup logic in app.py around the process_queue_loop and
recover_creating_entries flow to also launch a per-project worker when is_multi
is true, or otherwise bypass throttling for multi-project mode. Use the existing
_pr_session_factory, cfg.coderabbit_quota, and cfg.github_repo setup as the
place to wire in the additional worker.
In `@sova/dashboard/routers/quota.py`:
- Around line 67-115: Add endpoint coverage for pr_queue_status / GET
/quota/pr-queue in tests/test_coderabbit_quota.py. Create one test for the
disabled path that asserts the response is {"enabled": False, "pending": 0,
"entries": []}, and another for the enabled path that seeds PRCreationQueue data
and verifies the returned pending count plus populated entries fields. Use the
same setup patterns already used for the other quota endpoint tests so the new
route is exercised through the router.
In `@sova/db/models.py`:
- Around line 442-446: The PR queue indexes in the model’s __table_args__ only
cover status, task_run_id, and enqueued_at, so the hot queries in process_queue
and the /quota/pr-queue path still miss project_slug and can’t use a single
efficient index. Update the model’s index set on the PR queue table to add a
composite index for the shared filter/order pattern using project_slug, status,
and enqueued_at, and keep the existing indexes only if they still serve other
query paths.
In `@sova/supervisor/pr_throttle.py`:
- Around line 99-104: The function signatures for poll_until_created and
process_queue_loop are missing type annotations for session_factory, which
violates the project’s typing guideline. Add an explicit callable/awaitable
session factory type to both signatures, and import the needed typing symbols
(such as Callable and Awaitable) so the parameter is fully annotated wherever it
is used.
- Around line 180-241: Persist the PRQueueStatus.CREATING state before calling
git_ops.create_pr inside process_queue so a crash cannot roll it back to PENDING
and re-create the PR on restart. Update the flow around entry.status,
session.flush/session.commit, and the create_pr call in process_queue to make
the CREATING transition durable before any GitHub/network work, while keeping
run_post_create_side_effects and the PR CREATED/task_run updates after the PR
exists. Also ensure the existing error handling still marks failures correctly
if create_pr raises.
🪄 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: 601d7142-1da4-4de2-9f49-66daf38d7627
📒 Files selected for processing (7)
sova/core/steps/create_pr.pysova/dashboard/app.pysova/dashboard/routers/quota.pysova/dashboard/services/agent_db.pysova/db/models.pysova/supervisor/pr_throttle.pytests/test_pr_throttle.py
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
xsovad06
left a comment
There was a problem hiding this comment.
PR Review: feat(#294): PR creation throttle for CodeRabbit rate limit compliance
Summary
PR #306 adds a DB-backed PR creation queue for CodeRabbit rate limit compliance. When coderabbit_quota.enabled = true, CreatePRStep enqueues PR creation data instead of calling GitHub immediately. A background process_queue_loop drains entries one at a time, respecting the quota window. 1 commit, 8 files, 1552 additions. CI fully green.
Findings
[HIGH] Correctness -- Missing Alembic migration for PRCreationQueue table
Location: sova/db/models.py:420-447
Problem: The new PRCreationQueue model has no Alembic migration. Last migration is 015_add_coderabbit_events.py. In PostgreSQL deployments using Alembic, the table will not be created. The create_all self-healing fallback handles SQLite only.
Suggestion: Generate a migration: alembic revision --autogenerate -m "add_pr_creation_queue".
[HIGH] Correctness -- run_post_create_side_effects uses get_project_dir() without guaranteed context
Location: sova/supervisor/pr_throttle.py:292-296
Problem: run_post_create_side_effects() calls get_project_dir() to load config and create an adapter. This relies on per-request context set by dashboard middleware. But this function is called from process_queue() in a background task -- not in a request context. get_project_dir() may return None, causing load_config(None) to use CWD instead of the correct project directory.
Suggestion: Pass project_dir as a parameter instead of relying on the context variable. The queue entry already has project_slug and repo.
[MEDIUM] Consistency -- Non-standard __import__("typing").TYPE_CHECKING pattern
Location: sova/core/steps/create_pr.py:18
Problem: Uses if __import__("typing").TYPE_CHECKING: instead of the standard from typing import TYPE_CHECKING; if TYPE_CHECKING: used in 16+ other files.
Suggestion: Use the standard pattern for consistency.
[MEDIUM] Correctness -- _finalize_task_run dequeues only on non-done status
Location: sova/dashboard/services/agent_db.py:161
Problem: Dequeue is guarded by if status != "done". A run marked "done" without its queue entry being processed leaves a PENDING entry that the processor will attempt to create a duplicate PR from. process_queue calls git_ops.create_pr directly without the _try_adopt_existing_pr dedup check.
Suggestion: Either always dequeue regardless of terminal status, or add PR dedup to process_queue.
[LOW] Code Quality -- Bare except Exception without chaining
Location: sova/dashboard/routers/quota.py:113-115
Problem: except Exception: re-raises as HTTPException without from exc, losing traceback chain (Ruff B904).
Suggestion: raise HTTPException(...) from exc
Confirmed Bot Findings
All 7 CodeRabbit findings from the initial review have been addressed in the current code:
_session_factory/_pr_session_factoryreturn type annotations -- fixed- Composite index
ix_pr_queue_project_status_enqueued-- added SessionFactorytype alias -- applied to all signatures- 3-phase transaction pattern for CREATING durability -- implemented
- Multi-project worker startup -- added
- PR queue endpoint tests -- added
Verdict
Request changes -- two HIGH findings should be resolved:
- Missing Alembic migration for
PRCreationQueue run_post_create_side_effectscontext variable dependency in background task
What's Done Well
- 3-phase transaction architecture -- CREATING committed before network call, fields extracted to locals, failures handled in separate transactions. Prevents crash-recovery duplicates.
- Thorough test coverage -- 910 lines covering all code paths including edge cases (stale entries, quota exhaustion, fallback paths, loop lifecycle).
- Clean opt-in design -- gated behind
coderabbit_quota.enabled, graceful fallback on enqueue failure, original code path unchanged.
|
All review findings addressed in e7595c7 (squashed into the feature commit): [HIGH] Missing Alembic migration: Added [HIGH] [MEDIUM] Non-standard [MEDIUM] Dequeue only on non-done status: Removed the [LOW] Bare CI: all checks green. |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|



Summary
Automated changes for: feat(supervisor): PR creation throttle for CodeRabbit rate limit compliance
Closes #294
Context
Problem
CreatePRStepcreates PRs immediately, regardless of CodeRabbit quota availability. When multiple agents complete development simultaneously, they create 3-4 PRs within minutes, exhausting the 4/hour free-tier limit. Rate-limited PRs are often merged before a review slot opens, resulting in zero code review.Solution
Queue PR creation and drip-feed them at intervals that respect the CodeRabbit rate limit. Fully opt-in -- zero behavior change when
coderabbit.enabled = false...Commits
Files changed