Skip to content

fix: preserve daemon worker routes on request timeouts - #1181

Merged
willkill07 merged 1 commit into
NVIDIA:mainfrom
willkill07:fix/daemon-request-timeouts
Oct 2, 2026
Merged

willkill07 merged 1 commit into
NVIDIA:mainfrom
willkill07:fix/daemon-request-timeouts

Conversation

@willkill07

@willkill07 willkill07 commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Overview

Preserve the assigned worker route when a request exceeds the daemon's 60-second response-header deadline. Previously, a slow middleware or provider request returned 504 and also forced the worker to reconnect, temporarily sending subsequent requests through passthrough or returning 503 with --require-worker.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Return 504 for a response-header timeout while retaining the worker route. Transport failures, response-body failures, and explicit worker route rejection continue to trigger recovery.
  • Emit worker_request_failed for the timeout and include a specific reason in worker_communication_failed.
  • Report the actual control cancellation reason: activation cancellation, activation failure, activation expiry, or worker communication failure. Previously, all these paths reported activation_expired.
  • Add a regression that advances virtual time through the deadline and verifies that the next request reaches the same worker in both normal and strict routing modes.
  • Update daemon reference and operations documentation.

This PR addresses broker timeout handling and diagnostics. The runtime compaction deadlock reported in #1180 requires a separate fix.

Validation:

  • The new regression failed against the original implementation and passed after the fix.
  • just test-rust: all 5,609 workspace and standalone example tests passed before rebasing onto the updated upstream main.
  • After rebase: cargo nextest run --locked -p nemo-relay-cli --features __test-cli-port-override,__skip-implicit-config --profile ci -E 'test(daemon::broker::server::)' with NEMO_RELAY_TEST_SKIP_IMPLICIT_CONFIG=1 and an isolated XDG_CONFIG_HOME: all 94 daemon server/socket tests passed without retries. An initial run encountered a daemon trust-pin collision and passed on retry.
  • cargo clippy --locked -p nemo-relay-cli --lib --tests --features __test-cli-port-override,__skip-implicit-config -- -D warnings
  • cargo fmt --all -- --check and git diff --check
  • just docs: passed; Fern skipped the remote redirect comparison after HTTP 403.
  • uv run --no-sync pre-commit run: all applicable staged-change hooks passed, including documentation link checks, workspace Clippy, and workspace build checks.

Where should the reviewer start?

Start with forward_to_worker in crates/cli/src/daemon/broker/server.rs and worker_response_head_timeout_preserves_the_route_and_next_request in crates/cli/tests/coverage/daemon/server_tests.rs. Then review cancellation-reason propagation through cancel_staged_activation and Hub::cancel_worker.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07
willkill07 requested review from a team as code owners October 2, 2026 22:30
@github-actions github-actions Bot added size:S PR is small Bug issue describes bug; PR fixes bug lang:rust PR changes/introduces Rust code labels Oct 2, 2026
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/NeMo-Relay/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Enterprise
  • Run ID: 179a6af9-284b-407e-ba60-487c75cca3a7
📥 Commits

Reviewing files that changed from the base of the PR and between 20016c6 and 208b096.

📒 Files selected for processing (5)
  • crates/cli/src/daemon/broker/server.rs
  • crates/cli/src/daemon/broker/server/socket.rs
  • crates/cli/tests/coverage/daemon/server_tests.rs
  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: Rust / Package (windows-amd64)
  • GitHub Check: Rust / Package (macos-arm64)
  • GitHub Check: Rust / Package (linux-amd64)
  • GitHub Check: Rust / Package (linux-musl-arm64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Rust / Package (linux-arm64)
  • GitHub Check: Rust / Package (windows-arm64)
  • GitHub Check: Rust / Package (linux-musl-amd64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (6)
Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.

⚙️ CodeRabbit configuration file

Files:

  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx
Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.

⚙️ CodeRabbit configuration file

Files:

  • crates/cli/tests/coverage/daemon/server_tests.rs
Source excerpt: In MDX files, top-of-file comments must use JSX comment delimiters: `{/*` to open and `*/}` to close.

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Files:

  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx
Source excerpt: Verify MDX files use JSX delimiters for top-of-file SPDX comments.

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

Files:

  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx
Source excerpt: Search documentation source for references to the old version and update current-version install commands, package examples, and configuration examples to `` where appropriate: Review matches before changing th...

📄 CodeRabbit inference engine (.agents/skills/prepare-code-freeze/SKILL.md)

Files:

  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx
Source excerpt: Preserve MDX front matter and the JSX SPDX comment.

📄 CodeRabbit inference engine (.agents/skills/draft-release-notes/SKILL.md)

Files:

  • docs/daemon/operations.mdx
  • docs/daemon/reference.mdx
🔇 Additional comments (7)
crates/cli/src/daemon/broker/server.rs (1)

775-779: LGTM!

Also applies to: 822-822, 1768-1782, 1784-1787, 1794-1799, 1992-1992, 2002-2004, 2012-2012, 2214-2214, 2230-2230, 2247-2247, 2265-2265

crates/cli/src/daemon/broker/server/socket.rs (1)

160-160: LGTM!

Also applies to: 162-162, 768-768

crates/cli/tests/coverage/daemon/server_tests.rs (2)

844-932: LGTM!


2685-2690: LGTM!

docs/daemon/operations.mdx (2)

163-163: LGTM!


174-182: LGTM!

docs/daemon/reference.mdx (1)

442-446: LGTM!


Walkthrough

The daemon now returns response-head timeouts without disconnecting the worker or changing its route when no route rejection occurs. Worker communication failures and staged-worker cancellations pass explicit reasons to cancellation handling.

Changes

Daemon worker handling

Layer / File(s) Summary
Propagate activation cancellation reasons
crates/cli/src/daemon/broker/server.rs, crates/cli/src/daemon/broker/server/socket.rs
Staged-worker cancellation now passes an explicit reason through socket cancellation. Activation cancellation, activation failure, expiry, and MCP-release paths supply reasons.
Handle forwarding timeouts and failures
crates/cli/src/daemon/broker/server.rs, crates/cli/tests/coverage/daemon/server_tests.rs, docs/daemon/*
Response-head timeouts without route rejection return without worker communication failure handling. Other communication failures pass a reason and retain the existing failure handling. Tests and documentation describe timeout and failure behavior.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 208b0

The change preserves worker routes after response-header timeouts, and the added regression covers a successful subsequent request in both routing modes. No identified issue blocks merging after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 3 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title uses the required Conventional Commits format, uses the allowed lowercase type "fix", summarizes the main change, contains 54 characters, and has no trailing period.
Description check ✅ Passed The description includes all required template sections, completed checkboxes, implementation details, reviewer guidance, related issue information, and validation results. It clearly matches the pull…
Full details: Docstring Coverage

Explanation

Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 16 functions across 3 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

@willkill07 willkill07 self-assigned this Oct 2, 2026
@willkill07 willkill07 added this to the 0.10 milestone Oct 2, 2026
@willkill07
willkill07 enabled auto-merge (squash) October 2, 2026 23:13
@willkill07
willkill07 merged commit dd86041 into NVIDIA:main Oct 2, 2026
48 checks passed
willkill07 added a commit that referenced this pull request Oct 2, 2026
#### Overview

Compaction can deadlock when a dynamic plugin's conditional subscriber
gate snapshots a scope stack that the compaction path holds for writing.
Legitimate long compaction and model/tool execution can also exceed
fixed response and plugin RPC deadlines. Release the scope lock before
evaluating gates and let long execution complete or end through caller
cancellation.

- [x] I confirm this contribution is my own work, or I have the right to
submit it under this project's license.
- [x] I searched existing issues and open pull requests, and this does
not duplicate existing work.

#### Details

- Preserve subscriber selection before marking the agent fresh, while
evaluating conditional plugin callbacks without the compaction write
guard.
- Default daemon, worker, and standalone gateway provider waits to no
deadline. Add `[upstream] response_timeout_secs` (`0` disables it),
include it in the gateway bootstrap fingerprint, and document its
behavior.
- Remove fixed RPC deadlines from tool/LLM execution intercepts and LLM
stream opening. Keep connection, startup, health, and short callback
deadlines separate; preserve caller cancellation and resource cleanup.
- Add a process-bounded deadlock regression and simulated hour-long wait
tests covering completion, cancellation, cleanup, and explicit timeout
expiry.
- Build on merged #1181 (`dd86041ee5cd8a685605f57820de80db6f05e4ba`).
Adapt its route-preservation regression to configure a 60-second timeout
and update its deadline documentation. This PR targets the updated
`main` and contains only the compaction and execution-deadline changes.

Validation: `just test-rust`, `just test-python`, `just test-node`,
`just docs`, and `uv run pre-commit run`. The Rust suite and staged
hooks validate the combined source with #1181. Rebasing onto its squash
commit preserved the tested tree exactly. Python, Node, and
documentation checks passed for the compaction patch before stacking.
The documentation redirect comparison was skipped because FDR returned
HTTP 403; other documentation checks passed.

Behavior change: execution and provider waits default to no deadline. A
positive `response_timeout_secs` enables response-header limits on
daemon/worker hops and idle read limits in the standalone gateway. There
are no public API signature or worker protocol changes.

#### Where should the reviewer start?

Start with `crates/core/src/api/scope.rs` and
`crates/core/tests/integration/worker_plugin_tests.rs` for the lock
ordering and deadlock reproduction. Then review
`crates/cli/src/configuration/types.rs`, its forwarding call sites, and
`crates/core/src/plugin/dynamic/worker.rs` for timeout and cancellation
behavior. The PR diff starts from the merged #1181 fix.

#### Related Issues: (use one of the action keywords Closes / Fixes /
Resolves / Relates to)

- Closes #1180
- Relates to #1181


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added an optional `response_timeout_secs` setting for provider
response waits. It defaults to `0` (no deadline); positive values set a
limit. In the standalone gateway, the setting also limits idle
response-body reads.
* Tool and LLM execution callbacks can wait for downstream work without
a fixed RPC deadline; caller cancellation still ends the invocation.
* **Documentation**
* Updated configuration and plugin guidance to explain timeout behavior,
cancellation, and the separation between provider response waits and
other deadlines.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07
willkill07 deleted the fix/daemon-request-timeouts branch October 7, 2026 00:46

This branch was successfully deployed

1 active deployment
fern — 208b0960 Deployed Oct 2, 2026 by willkill07 via Clean up docs preview #5271
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug issue describes bug; PR fixes bug lang:rust PR changes/introduces Rust code size:S PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants