perf(onboard): use deadlines for gateway health waits - #6489
Conversation
📝 WalkthroughWalkthroughGateway health polling now uses deadline-based timing with computed wait budgets. The package-managed gateway path, related tests, and onboarding startup error handling were updated to use the new behavior and preserve more specific failure messages. ChangesDeadline-based health wait
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
de99d4a to
33fcc1c
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/lib/onboard/gateway-health-wait.test.ts (2)
104-104: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider adding a local issue reference to the new test title.
This test is the core regression coverage for the deadline-vs-cap behavior tied to
#3768; as per coding guidelines for**/*.test.ts, consider a trailing(#3768)suffix.🤖 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 `@src/lib/onboard/gateway-health-wait.test.ts` at line 104, Update the new test title in gateway-health-wait.test.ts to include the local issue reference suffix, so the regression coverage for the deadline-vs-cap behavior is clearly tied to `#3768`; adjust the it(...) description for the polling test to end with "(`#3768`)".Source: Coding guidelines
29-41: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
makeVirtualClockduplicated across two test files.The same helper (minus the
sleeperfield) is redefined insrc/lib/onboard/docker-driver-gateway-service.test.ts. Consider extracting to a shared test utility.🤖 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 `@src/lib/onboard/gateway-health-wait.test.ts` around lines 29 - 41, The makeVirtualClock helper is duplicated across gateway-health-wait.test.ts and docker-driver-gateway-service.test.ts, so extract the shared clock setup into a common test utility and reuse it from both tests. Keep the existing behavior used by makeVirtualClock, advance, now, and sleeper, but centralize the implementation so future changes only need to be made once.
🤖 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 `@src/lib/onboard.ts`:
- Line 1899: The final startup failure path is masking the timeout/deadline
message generated in the retry body. Update the outer catch in the gateway
startup flow around the healthWait retry logic so terminal failures preserve and
rethrow the original deadline-aware error instead of replacing it with the
generic “Gateway failed to start” message. Keep the existing timeout throw that
includes healthWait.count and healthWait.interval, and ensure that same error
text reaches the caller on the last failure.
---
Nitpick comments:
In `@src/lib/onboard/gateway-health-wait.test.ts`:
- Line 104: Update the new test title in gateway-health-wait.test.ts to include
the local issue reference suffix, so the regression coverage for the
deadline-vs-cap behavior is clearly tied to `#3768`; adjust the it(...)
description for the polling test to end with "(`#3768`)".
- Around line 29-41: The makeVirtualClock helper is duplicated across
gateway-health-wait.test.ts and docker-driver-gateway-service.test.ts, so
extract the shared clock setup into a common test utility and reuse it from both
tests. Keep the existing behavior used by makeVirtualClock, advance, now, and
sleeper, but centralize the implementation so future changes only need to be
made once.
🪄 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: CHILL
Plan: Enterprise
Run ID: edff3e71-1387-49b1-9175-b3a869670569
📒 Files selected for processing (5)
src/lib/onboard.tssrc/lib/onboard/docker-driver-gateway-service.test.tssrc/lib/onboard/docker-driver-gateway-service.tssrc/lib/onboard/gateway-health-wait.test.tssrc/lib/onboard/gateway-health-wait.ts
33fcc1c to
21fca10
Compare
apurvvkumaria
left a comment
There was a problem hiding this comment.
This is a useful deadline conversion for two gateway paths, but it does not yet satisfy the issue it closes:
dco-checkis failing because the PR body has no contributor declaration. Please addSigned-off-by: Ho Lim <subhoya@gmail.com>to the PR description yourself; maintainers cannot do that on a contributor's behalf.Fixes #3768is too broad for the current diff. #3768 covers the remaining sandbox, dashboard, gateway-recovery, agent-gateway, and create-stream readiness loops, plus fast polling with capped backoff. This PR changes the gateway health wait and package-managed Docker-driver path and retains a fixed interval. Either complete the remaining acceptance criteria or change the linkage to a partial/mitigation statement so #3768 remains open.- The exact-head static gate is red because
test/langchain-deepagents-code-image.test.tsis 1501 lines against the 1500-line budget. Rebase onto a green base or split/ratchet the test without raising the ceiling, then rerun the required gate.
The deadline-aware error and virtual-clock coverage look appropriate for the narrower partial scope.
Signed-off-by: Ho Lim <subhoya@gmail.com>
21fca10 to
258433c
Compare
apurvvkumaria
left a comment
There was a problem hiding this comment.
The earlier DCO, issue-linkage, and stale line-budget concerns are resolved on this head. One blocking deadline regression remains:
getGatewayHealthWaitBudgetMs() converts a positive poll count with healthPollIntervalSeconds = 0 into a 1 ms deadline. The shared waiter checks that deadline before each probe, so scheduling overhead can produce zero probes; otherwise the gateway receives roughly one probe. The previous maxAttempts behavior supported the configured number of immediate probes. Zero is an accepted environment value, is used by existing tests, and the package-managed happy-path test changes its interval from 0 to 1, masking the compatibility break.
Please either validate and reject a zero interval explicitly, or preserve a bounded zero-interval path that still performs the configured probes. Add deterministic coverage for pre-probe expiry and count > 1 with interval zero in both the shared budget helper and package-managed caller. Also add a rejected/slow probe case that proves the original error and deadline behavior are preserved.
Relevant paths: src/lib/onboard/gateway-health-wait.ts around lines 22-30 and 78, plus src/lib/onboard/docker-driver-gateway-service.ts around lines 327-353.
I found no credential, authorization, SSRF, sandbox-escape, or dependency vulnerability in the six-file exact-head diff. This request is correctness and negative-test coverage for an accepted configuration boundary.
Use bounded immediate attempts when the interval is zero. Positive intervals remain deadline-driven. Co-authored-by: Ho Lim <subhoya@gmail.com> Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
|
Maintainer follow-up
Validation on the pushed head: 24 focused tests passed; CLI build and type-check passed; formatting, repository checks, test-size checks, and secret scanning passed. The change request stays in place until fresh CI and automated review settle. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/lib/onboard/gateway-health-wait.ts (1)
22-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract shared normalization helper to reduce duplication.
The
Number.isFinite(x) ? Math.max(0, x) : 0pattern is repeated near-verbatim ingetGatewayHealthWaitBudgetMs(lines 26-29),formatGatewayHealthWaitLimit(lines 52-58), andcreateGatewayHealthWaitOptions(lines 71-76). A singleclampNonNegativeFinitehelper would remove the drift risk across these three call sites.♻️ Proposed refactor
+function clampNonNegativeFinite(value: number): number { + return Number.isFinite(value) ? Math.max(0, value) : 0; +} + export function getGatewayHealthWaitBudgetMs( healthPollCount: number, healthPollIntervalSeconds: number, ): number { - const normalizedCount = Number.isFinite(healthPollCount) ? Math.max(0, healthPollCount) : 0; - const normalizedIntervalSeconds = Number.isFinite(healthPollIntervalSeconds) - ? Math.max(0, healthPollIntervalSeconds) - : 0; + const normalizedCount = clampNonNegativeFinite(healthPollCount); + const normalizedIntervalSeconds = clampNonNegativeFinite(healthPollIntervalSeconds);Also applies to: 48-63, 65-97
🤖 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 `@src/lib/onboard/gateway-health-wait.ts` around lines 22 - 35, The same non-negative finite normalization logic is duplicated across getGatewayHealthWaitBudgetMs, formatGatewayHealthWaitLimit, and createGatewayHealthWaitOptions, so extract it into a shared clampNonNegativeFinite helper and use that helper at each call site to keep the behavior consistent and avoid drift.
🤖 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 `@src/lib/onboard/gateway-health-wait.ts`:
- Around line 22-35: The same non-negative finite normalization logic is
duplicated across getGatewayHealthWaitBudgetMs, formatGatewayHealthWaitLimit,
and createGatewayHealthWaitOptions, so extract it into a shared
clampNonNegativeFinite helper and use that helper at each call site to keep the
behavior consistent and avoid drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: efeef74e-ef59-44fe-8481-90aa51c0d98e
📒 Files selected for processing (4)
src/lib/onboard/docker-driver-gateway-service.test.tssrc/lib/onboard/docker-driver-gateway-service.tssrc/lib/onboard/gateway-health-wait.test.tssrc/lib/onboard/gateway-health-wait.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/lib/onboard/docker-driver-gateway-service.ts
<!-- markdownlint-disable MD041 --> ## Summary This replacement carries Ho Lim's work from #6489 onto current `main` and preserves Ho as a commit co-author. It replaces fixed attempt caps with bounded gateway-health deadlines while retaining deterministic, configured immediate probes when the poll interval is zero. ## Related Issue Refs #3768. This is a partial mitigation for the gateway-health and package-managed Docker-driver paths; it intentionally leaves the broader readiness-loop issue open. ## Changes - Derive positive-interval gateway health waits from one deadline budget. - Preserve the configured number of bounded immediate probes for a zero interval. - Keep deadline-aware terminal errors intact through the onboarding failure path. - Share a deterministic virtual clock and add positive, zero-interval, rejection, and slow-probe coverage. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [ ] Docs updated for user-facing behavior changes - [x] Docs not applicable — justification: the change preserves the existing readiness contract and only corrects internal polling semantics and terminal diagnostics. - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [x] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: the exact fixed tree was reviewed on #6489 with no credential, authorization, SSRF, sandbox-escape, or dependency blocker; this replacement is tree-equivalent on current main. - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification <!-- Check each applicable item only when supported by the requested evidence. Run targeted tests once per relevant change set and rerun after later edits or hook autofixes that can affect the tested behavior. Do not rerun hook-covered checks. --> - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `24/24` focused gateway tests and `77/77` targeted onboarding/integration tests passed. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [ ] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- <!-- DCO sign-off is required in this PR description, and every commit must appear as Verified in GitHub. Run: git config user.name && git config user.email --> Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Gateway health checks now use deadline/budget-based timing, including an immediate-probe mode when the poll interval is zero. * Health-wait timing can be driven by an injected clock source for deterministic behavior. * **Bug Fixes** * Gateway startup failures now preserve the original thrown error when available, with improved timeout/deadline messaging. * **Tests** * Added a virtual clock helper and updated gateway health/startup tests to use deterministic time, including new zero-interval and deadline-expiration coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> Co-authored-by: Ho Lim <subhoya@gmail.com>
<!-- markdownlint-disable MD041 --> ## Summary This replacement carries Ho Lim's work from NVIDIA#6489 onto current `main` and preserves Ho as a commit co-author. It replaces fixed attempt caps with bounded gateway-health deadlines while retaining deterministic, configured immediate probes when the poll interval is zero. ## Related Issue Refs NVIDIA#3768. This is a partial mitigation for the gateway-health and package-managed Docker-driver paths; it intentionally leaves the broader readiness-loop issue open. ## Changes - Derive positive-interval gateway health waits from one deadline budget. - Preserve the configured number of bounded immediate probes for a zero interval. - Keep deadline-aware terminal errors intact through the onboarding failure path. - Share a deterministic virtual clock and add positive, zero-interval, rejection, and slow-probe coverage. ## Type of Change - [x] Code change (feature, bug fix, or refactor) - [ ] Code change with doc updates - [ ] Doc only (prose changes, no code sample modifications) - [ ] Doc only (includes code sample changes) ## Quality Gates <!-- Check exactly one tests line and one docs line. Check other lines when applicable. Add every requested justification or approval reference. --> - [x] Tests added or updated for changed behavior - [ ] Existing tests cover changed behavior — justification: - [ ] Tests not applicable — justification: - [ ] Docs updated for user-facing behavior changes - [x] Docs not applicable — justification: the change preserves the existing readiness contract and only corrects internal polling semantics and terminal diagnostics. - [x] Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging) - [x] Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: the exact fixed tree was reviewed on NVIDIA#6489 with no credential, authorization, SSRF, sandbox-escape, or dependency blocker; this replacement is tree-equivalent on current main. - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification <!-- Check each applicable item only when supported by the requested evidence. Run targeted tests once per relevant change set and rerun after later edits or hook autofixes that can affect the tested behavior. Do not rerun hook-covered checks. --> - [x] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub - [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or `npm run check:diff` passed when hooks were skipped or unavailable - [x] Targeted behavior tests pass for the current change set, or tests are marked not applicable above — `24/24` focused gateway tests and `77/77` targeted onboarding/integration tests passed. - [ ] Applicable broad gate passed — `npm test` for broad runtime/test-harness changes; `npm run check` for repo-wide validation/coverage changes — command/result: - [x] Quality Gates section completed with required justifications or waivers - [x] No secrets, API keys, or credentials committed - [ ] `npm run docs` builds without warnings (doc changes only) - [ ] Doc pages follow the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md) (doc changes only) - [ ] New doc pages include SPDX header and frontmatter (new pages only) --- <!-- DCO sign-off is required in this PR description, and every commit must appear as Verified in GitHub. Run: git config user.name && git config user.email --> Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Gateway health checks now use deadline/budget-based timing, including an immediate-probe mode when the poll interval is zero. * Health-wait timing can be driven by an injected clock source for deterministic behavior. * **Bug Fixes** * Gateway startup failures now preserve the original thrown error when available, with improved timeout/deadline messaging. * **Tests** * Added a virtual clock helper and updated gateway health/startup tests to use deterministic time, including new zero-interval and deadline-expiration coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: Apurv Kumaria <akumaria@nvidia.com> Co-authored-by: Ho Lim <subhoya@gmail.com>
Refs #3768.
Summary
Validation
npx @biomejs/biome check src/lib/onboard.ts src/lib/onboard/gateway-health-wait.ts src/lib/onboard/gateway-health-wait.test.ts src/lib/onboard/docker-driver-gateway-service.ts src/lib/onboard/docker-driver-gateway-service.test.tsnpx vitest run --project cli src/lib/onboard/gateway-health-wait.test.ts src/lib/onboard/docker-driver-gateway-service.test.tsnpx vitest run --project cli --project integration test/onboard.test.ts test/gateway-final-failure-cleanup.test.ts src/lib/onboard/gateway-start-failure-integration.test.tsnpm run build:clinpm run test-conditionals:scan -- --top 25npm run source-shape:checknpm run check:diffSummary by CodeRabbit
Signed-off-by: Ho Lim subhoya@gmail.com