Skip to content

feat(api): add bounded admission control - #4467

Open
poroh wants to merge 1 commit into
NVIDIA:mainfrom
poroh:feat/4212-bounded-api-admission-control
Open

feat(api): add bounded admission control#4467
poroh wants to merge 1 commit into
NVIDIA:mainfrom
poroh:feat/4212-bounded-api-admission-control

Conversation

@poroh

@poroh poroh commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Adds bounded admission control for Forge gRPC and admin HTTP requests. It limits executing and pending work before handlers access the database, returns transport-appropriate overload responses, and releases permits when handler execution completes.

Also prevents stalled Scout streams from holding capacity indefinitely by timing out while waiting for the initial Init message.

Related issues

Closes #4212
Related: #4215

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

Additional Notes

@copy-pr-bot

copy-pr-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue [#4212] with shared limits, configuration, route handling, timeouts, permit cleanup, overload responses, metrics, and tests.
Out of Scope Changes check ✅ Passed The configuration, documentation, tests, metrics, and Scout stream timeout support the admission-control objectives and are in scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title clearly summarizes the main change: adding bounded API admission control.
Description check ✅ Passed The description directly explains the admission-control feature, Scout stream timeout, related issues, and testing.

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

@poroh

poroh commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test ed10f57

@github-actions

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
crates/api-core/src/cfg/file.rs (1)

3951-4023: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider the repository table-test helpers for these validation cases.

The three new tests map inputs to Result outcomes. This file already imports check_values and scenarios!. A single table would replace the hand-rolled ZeroOut alias, the manual loop, and the duplicated upper-bound helper.

Example shape:

scenarios!(
    run = |config: ApiAdmissionControlConfig| config.validate().map_err(|error| error.to_string());
    "bounds are validated only when enabled" { /* cases */ }
);

As per coding guidelines: "Use table-driven tests for functions mapping inputs to outputs, errors, or observable results. Use scenarios! with Outcome for Result-returning operations, value_scenarios! for total operations, and direct check_cases/check_values when macros obscure the table."

🤖 Prompt for 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.

In `@crates/api-core/src/cfg/file.rs` around lines 3951 - 4023, Refactor the
admission-control validation tests around
api_admission_control_only_validates_bounds_when_enabled and the upper-bound
tests into a single scenarios! table using the imported check_values and Outcome
patterns. Replace the ZeroOut alias, manual iteration, and
assert_api_admission_semaphore_bound helper with table cases that cover disabled
zero bounds, zero-value validation errors, and Tokio semaphore maximum
acceptance/rejection while preserving field and maximum checks.

Source: Coding guidelines

crates/api-core/src/admission.rs (1)

606-612: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the bounded yield loop with a deterministic wait.

The loop yields at most 100 times and then asserts the occupancy. Scheduler variation can exhaust the budget before the pending task reaches the semaphore, which makes the test flaky in CI. A tokio::time::timeout around a Notify, or a timeout around the occupancy poll, removes the fixed iteration count.

♻️ Proposed change to remove the fixed iteration budget
-        for _ in 0..100 {
-            if controller.occupancy() == (0, 0) {
-                break;
-            }
-            tokio::task::yield_now().await;
-        }
-        assert_eq!(controller.occupancy(), (0, 0));
+        tokio::time::timeout(Duration::from_secs(5), async {
+            while controller.occupancy() != (0, 0) {
+                tokio::task::yield_now().await;
+            }
+        })
+        .await
+        .expect("pending request should occupy the queue slot");
🤖 Prompt for 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.

In `@crates/api-core/src/admission.rs` around lines 606 - 612, Replace the fixed
100-iteration yield loop after the controller operation with a deterministic
asynchronous wait, using a tokio::time::timeout around an appropriate Notify or
occupancy-poll future. Ensure the wait completes when controller.occupancy()
reaches (0, 0), then retain the final assertion and fail clearly if the timeout
expires.
🤖 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.

Nitpick comments:
In `@crates/api-core/src/admission.rs`:
- Around line 606-612: Replace the fixed 100-iteration yield loop after the
controller operation with a deterministic asynchronous wait, using a
tokio::time::timeout around an appropriate Notify or occupancy-poll future.
Ensure the wait completes when controller.occupancy() reaches (0, 0), then
retain the final assertion and fail clearly if the timeout expires.

In `@crates/api-core/src/cfg/file.rs`:
- Around line 3951-4023: Refactor the admission-control validation tests around
api_admission_control_only_validates_bounds_when_enabled and the upper-bound
tests into a single scenarios! table using the imported check_values and Outcome
patterns. Replace the ZeroOut alias, manual iteration, and
assert_api_admission_semaphore_bound helper with table cases that cover disabled
zero bounds, zero-value validation errors, and Tokio semaphore maximum
acceptance/rejection while preserving field and maximum checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9395923a-9161-4595-a068-eb5778a1ed58

📥 Commits

Reviewing files that changed from the base of the PR and between 00e989f and ed10f57.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • book/src/configuration/configurability.md
  • crates/api-core/Cargo.toml
  • crates/api-core/src/admission.rs
  • crates/api-core/src/cfg/README.md
  • crates/api-core/src/cfg/file.rs
  • crates/api-core/src/cfg/load.rs
  • crates/api-core/src/handlers/scout_stream.rs
  • crates/api-core/src/lib.rs
  • crates/api-core/src/listener.rs
  • crates/api-core/src/test_support/default_config.rs
  • docs/observability/core_metrics.md

@poroh
poroh marked this pull request as ready for review August 1, 2026 02:40
@poroh
poroh requested a review from a team as a code owner August 1, 2026 02:40
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: add bounded API admission control

1 participant