Skip to content

[None][feat] support NIXL cache transceiver with Ray - #17295

Open
chuangz0 wants to merge 3 commits into
NVIDIA:mainfrom
chuangz0:ray_support_nixl_cache_transceiver
Open

[None][feat] support NIXL cache transceiver with Ray#17295
chuangz0 wants to merge 3 commits into
NVIDIA:mainfrom
chuangz0:ray_support_nixl_cache_transceiver

Conversation

@chuangz0

@chuangz0 chuangz0 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • support NIXL cache-transceiver rank discovery and metadata exchange with the Torch process group used by Ray
  • support both CPP and PYTHON cache-transceiver runtimes in the Ray disaggregated-serving example
  • re-enable the existing tp1/tp2 Ray disaggregated-serving coverage and add matching Python-runtime coverage
  • preserve access to internal libraries when packaging the NIXL wrapper so transfer-agent stub generation works without environment-specific library paths
  • share one AwaitResponseHelper.process_responses() implementation between regular and Ray RPC workers

Why

The NIXL transfer agent and agent connection manager assumed MPI for rank discovery and collective metadata exchange. Ray workers disable MPI and use a Torch process group, so NIXL cache transfer could not initialize correctly in that environment. In addition, the tp1 test was skipped under an unrelated bug and tp2 remained waived.

The Python-transceiver first-token flow can produce an empty response (None) for an iteration with no client-visible serialized result. The regular worker path already runs engine responses through _engine_response_callback, filters non-client responses, and appends deferred submission errors before IPC handling. RpcWorkerMixin.fetch_responses() bypassed that existing preprocessing and passed the raw None to IPC, where response.has_error() terminated the Ray RPC stream.

The existing callback/filter/deferred-error logic is factored into AwaitResponseHelper.process_responses(). Both the regular worker and Ray RPC worker call that shared function before responses_handler(). No PyExecutor or placement-group behavior is changed by this fix.

This follows the intent of #10259 while adapting it to the current cache-transceiver and ProcessGroup implementation.

Validation

  • signed-off commit hooks passed, including formatting, lint, YAML/test-list validation, DCO, pre-push pre-commit update, and confidentiality scan
  • clean full Release SM86 build from a new build directory completed, including the main bindings, libtensorrt_llm.so, NIXL wrapper, transfer-agent binding, executor, and UCX wrapper
  • nanobind stub generation completed as part of the clean build
  • a 581 MB wheel was built and installed into an isolated temporary directory with --no-deps
  • the installed wheel's NIXL wrapper has RUNPATH=$ORIGIN:$ORIGIN/nixl/, and ldd resolves libpg_utils.so from the same wheel
  • bare transfer-agent binding import and package import from the isolated wheel passed
  • isolated-wheel NIXL transfer-agent binding tests: 5 passed
  • isolated-wheel single-process Python cache-transceiver test: 1 passed
  • isolated-wheel NIXL initialization through a singleton Torch ProcessGroup passed with MPI disabled
  • Ray RPC preprocessing and event-loop error-broadcast tests: 7 passed
  • local final-code validation: CPP-runtime and PYTHON-runtime tp1 disaggregated-serving E2E each completed five concurrent requests; every request returned 32 completion tokens, and the existing disaggregated-test accuracy checks (The capital of Germany is Berlin, Asyncio is a Python library, and no Berlin Berlin) passed, with no NoneType.has_error, RPCStreamingError, or ray_executor_main_loop failure; context/generation shared one physical RTX A6000 through a temporary fractional placement adjustment that is not part of this PR

The B200/B300 tp1/tp2 CPP/PYTHON E2E cases should be rerun in CI with the final narrowed diff.

Dev Engineer Review

  • Added Torch process-group rank and world-size discovery for C++ and Python NIXL cache-transceiver runtimes.
  • Preserved MPI support and added single-process fallback behavior.
  • Updated Ray disaggregated-serving configuration to support CPP and PYTHON transceiver runtimes.
  • Updated NIXL wrapper linking and RPATH handling for internal libraries.
  • Shared response preprocessing between regular workers and Ray RPC workers.
  • Added rank-aware NIXL address generation and process-group utilities.
  • Configuration values and test-list paths are consistent.
  • No duplicate test-list entries or unintended waiver changes were identified.
  • Release SM86 builds, wheel imports, NIXL and Torch process-group tests, Ray RPC tests, and local tp1 C++/Python E2E tests passed. B200/B300 tp1/tp2 E2E coverage still requires CI reruns.

QA Engineer Review

  • Added test_ray_disaggregated_serving_python(ray_example_root, llm_venv, tp_size).
  • Refactored Ray disaggregated-serving coverage for C++ and Python runtimes.
  • Removed the unconditional single-device tensor-parallel skip.
  • Added unittest/executor/test_rpc_worker_mixin.py with response and callback coverage.
  • Added the RPC worker test to tests/integration/test_lists/test-db/l0_cpu.yml.
  • Added the Python Ray test to:
    • tests/integration/test_lists/test-db/l0_dgx_b200.yml
    • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • Removed the obsolete Ray tp2 waiver from tests/integration/test_lists/waives.txt.
  • All added test functions are covered by CI test-list entries.
  • Verdict: sufficient, with B200/B300 tp1/tp2 E2E CI reruns still required.

@chuangz0
chuangz0 force-pushed the ray_support_nixl_cache_transceiver branch 3 times, most recently from 0b89b30 to dd29ae5 Compare August 5, 2026 09:49
@chuangz0
chuangz0 marked this pull request as ready for review August 5, 2026 09:51
@chuangz0
chuangz0 requested review from a team as code owners August 5, 2026 09:51
@chuangz0

chuangz0 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change adds Torch process-group support to cache agents, switches Ray disaggregated serving to selectable NIXL runtimes, updates NIXL packaging paths, centralizes RPC response processing, and adds unit and integration coverage.

Changes

Cache transport runtime support

Layer / File(s) Summary
Process-group rank and agent-state exchange
cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.*
AgentConnectionManager stores rank and world size, selects MPI or Torch process-group collectives, supports single-process fallback, and uses the stored rank in logs.
NIXL agent initialization and addressing
cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/*, scripts/build_wheel.py
NixlTransferAgent uses MPI or Torch process-group identity, rank-aware ports, shared IP discovery, and IP#port addresses. Build configuration links Torch and pg_utils, and updates the wrapper RPATH.
Ray runtime selection and integration tests
examples/ray_orchestrator/disaggregated/disagg_serving_local.sh, tests/integration/defs/examples/test_ray.py, tests/integration/test_lists/test-db/*, tests/integration/test_lists/waives.txt
The serving script accepts CPP or PYTHON and configures NIXL. Ray tests cover both runtimes and update test lists and waivers.

RPC response processing

Layer / File(s) Summary
Shared response processing
tensorrt_llm/executor/base_worker.py, tensorrt_llm/executor/rpc_worker_mixin.py
AwaitResponseHelper.process_responses() centralizes callback filtering and temporary-error handling. fetch_responses uses the helper before invoking the response handler.
RPC response validation
tests/unittest/executor/test_rpc_worker_mixin.py, tests/integration/test_lists/test-db/l0_cpu.yml
Unit tests verify timeout propagation, callback filtering, temporary errors, response handling, and returned responses. The test is added to the CPU suite.

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

Sequence Diagram(s)

sequenceDiagram
  participant AgentConnectionManager
  participant PgHelper
  participant NixlTransferAgent
  participant RayServingScript
  AgentConnectionManager->>PgHelper: Discover rank and world size
  AgentConnectionManager->>AgentConnectionManager: Exchange serialized agent state
  NixlTransferAgent->>NixlTransferAgent: Build rank-aware IP#port address
  RayServingScript->>NixlTransferAgent: Configure selected CPP or PYTHON runtime
Loading

Possibly related PRs

Suggested reviewers: bowenfu

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding Ray support for the NIXL cache transceiver.
Description check ✅ Passed The description explains the problem, solution, scope, and extensive validation, although it does not reproduce the checklist section.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/integration/defs/examples/test_ray.py (1)

71-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add annotations and docstrings to the new test functions.

Add precise parameter types and -> None return types. Add Google-style docstrings for test_ray_disaggregated_serving_python and _run_ray_disaggregated_serving.

As per coding guidelines: “Annotate every function” and “use Google-style docstrings for classes and functions.”

🤖 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 `@tests/integration/defs/examples/test_ray.py` around lines 71 - 78, Add
precise type annotations, including -> None, to
test_ray_disaggregated_serving_python and _run_ray_disaggregated_serving. Add
concise Google-style docstrings to both functions documenting their purpose and
each parameter, using the existing parameter names and types.

Source: Coding guidelines

tests/unittest/executor/test_rpc_worker_mixin.py (1)

55-64: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add coverage for the empty-response stream path.

Test coverage summary:

  • Added: test_fetch_responses_processes_and_filters_engine_responses.
  • Modified: none.
  • Removed: none.
  • CI list: tests/integration/test_lists/test-db/l0_cpu.yml includes this test file.
  • Manual QA list: not applicable for this CPU-only unit test.
  • Verdict: needs follow-up.

The test covers timeout propagation, callback filtering, temporary errors, and queue delivery. It does not verify an empty Python-transceiver response through fetch_responses_loop_async() and confirm that polling continues until shutdown. Add that regression case.

As per path instructions, test-code changes under tests/** require changed-test, test-list, and coverage reporting. The PR objective identifies empty Python-transceiver responses as the regression target.

🤖 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 `@tests/unittest/executor/test_rpc_worker_mixin.py` around lines 55 - 64, Add a
regression test alongside
test_fetch_responses_processes_and_filters_engine_responses that exercises an
empty Python-transceiver response through fetch_responses_loop_async(), verifies
polling continues rather than terminating on the empty response, and confirms
the loop exits only after shutdown. Update the required changed-test, test-list,
and coverage reporting for this tests/** change.

Source: Path instructions

🤖 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 `@tensorrt_llm/executor/base_worker.py`:
- Around line 1125-1126: Update the temp_error_responses drain in
process_responses() to repeatedly call get_nowait() and catch queue.Empty to
terminate the loop. Remove the empty() check and blocking get() pattern,
preserving response collection while remaining safe for concurrent callers.

---

Nitpick comments:
In `@tests/integration/defs/examples/test_ray.py`:
- Around line 71-78: Add precise type annotations, including -> None, to
test_ray_disaggregated_serving_python and _run_ray_disaggregated_serving. Add
concise Google-style docstrings to both functions documenting their purpose and
each parameter, using the existing parameter names and types.

In `@tests/unittest/executor/test_rpc_worker_mixin.py`:
- Around line 55-64: Add a regression test alongside
test_fetch_responses_processes_and_filters_engine_responses that exercises an
empty Python-transceiver response through fetch_responses_loop_async(), verifies
polling continues rather than terminating on the empty response, and confirms
the loop exits only after shutdown. Update the required changed-test, test-list,
and coverage reporting for this tests/** change.
🪄 Autofix

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: 3191efaa-20ad-4408-9daf-54e33603d284

📥 Commits

Reviewing files that changed from the base of the PR and between 9564b3b and dd29ae5.

📒 Files selected for processing (15)
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.h
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/CMakeLists.txt
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.h
  • examples/ray_orchestrator/disaggregated/disagg_serving_local.sh
  • scripts/build_wheel.py
  • tensorrt_llm/executor/base_worker.py
  • tensorrt_llm/executor/rpc_worker_mixin.py
  • tests/integration/defs/examples/test_ray.py
  • tests/integration/test_lists/test-db/l0_cpu.yml
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
  • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • tests/integration/test_lists/waives.txt
  • tests/unittest/executor/test_rpc_worker_mixin.py
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt

Comment on lines +1125 to +1126
while not self.temp_error_responses.empty():
responses.append(self.temp_error_responses.get())

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 4 \
  'AwaitResponseHelper\(|process_responses\(|fetch_responses\(|temp_error_responses' \
  tensorrt_llm tests

Repository: NVIDIA/TensorRT-LLM

Length of output: 11158


🏁 Script executed:

# Check the class hierarchy and whether RpcWorkerMixin instances use both code paths
ast-grep outline tensorrt_llm/executor/rpc_worker_mixin.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 514


🏁 Script executed:

# Check the class hierarchy for workers that use RpcWorkerMixin
rg -n 'class.*RpcWorkerMixin' tensorrt_llm

Repository: NVIDIA/TensorRT-LLM

Length of output: 495


🏁 Script executed:

# Check if await_responses() and fetch_responses() are both called on the same instance
rg -n 'await_responses|fetch_responses' tensorrt_llm/executor/*.py --type py -B2 -A2 | head -80

Repository: NVIDIA/TensorRT-LLM

Length of output: 6557


🏁 Script executed:

# Check the event loop and threading model - look for async/threading context
rg -n 'Thread|asyncio|run_event_loop|threading' tensorrt_llm/executor/base_worker.py -A2 -B2 | head -100

Repository: NVIDIA/TensorRT-LLM

Length of output: 772


🏁 Script executed:

# Understand the ManagedThread context and how AwaitResponseHelper is used
rg -n 'ManagedThread|setup_mainloop' tensorrt_llm/executor/rpc_worker_mixin.py -B3 -A8

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check how AwaitResponseHelper.__call__ is invoked through the event loop
rg -n '_await_response_helper' tensorrt_llm/executor/base_worker.py -B2 -A2 | head -60

Repository: NVIDIA/TensorRT-LLM

Length of output: 549


🏁 Script executed:

# For RPC workers, check if fetch_responses runs on a separate thread from the event loop
rg -n 'fetch_responses_loop_async|setup_engine_remote' tensorrt_llm/executor/rpc_worker_mixin.py -B4 -A10

Repository: NVIDIA/TensorRT-LLM

Length of output: 1647


🏁 Script executed:

# Check which code path is active for RpcWorker instances
# Look at RpcWorker initialization and which methods are called
ast-grep outline tensorrt_llm/executor/rpc_worker.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 387


🏁 Script executed:

# Understand the setup_mainloop and what tasks run in it
rg -n 'setup_mainloop\|_fetch_responses_loop_async' tensorrt_llm/executor/base_worker.py -B5 -A15 | head -80

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check if RpcWorkerMixin instances use both __call__ (ManagedThread) and fetch_responses concurrently
rg -n 'GenerationExecutorWorker\|RayGPUWorker\|RpcWorker' tensorrt_llm/executor/ -A20 | grep -E 'class |setup_mainloop|__call__|fetch_responses' | head -40

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Look at how RpcWorker is instantiated and what setup it does
cat -n tensorrt_llm/executor/rpc_worker.py | head -200

Repository: NVIDIA/TensorRT-LLM

Length of output: 8322


🏁 Script executed:

# Search for AwaitResponseHelper.__call__ usage and which worker types use it
rg -n 'AwaitResponseHelper' tensorrt_llm/executor/ --type py -B3 -A3

Repository: NVIDIA/TensorRT-LLM

Length of output: 2624


🏁 Script executed:

# Check BaseWorker to see if it has ManagedThread setup
rg -n 'ManagedThread\|_mainloop\|AwaitResponseHelper.*__call__' tensorrt_llm/executor/base_worker.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check GenerationExecutorWorker to see if it uses both __call__ and fetch_responses
cat -n tensorrt_llm/executor/worker.py | head -150

Repository: NVIDIA/TensorRT-LLM

Length of output: 7434


🏁 Script executed:

# Look for where AwaitResponseHelper.__call__ is actually invoked
rg -n '__call__' tensorrt_llm/executor/base_worker.py -B5 -A5

Repository: NVIDIA/TensorRT-LLM

Length of output: 651


🏁 Script executed:

# Check if GenerationExecutorWorker has a main loop that calls AwaitResponseHelper
rg -n 'class GenerationExecutorWorker\|def main\|ManagedThread\|setup_mainloop\|_await_response' tensorrt_llm/executor/worker.py -B2 -A4

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check if RPC server is started in GenerationExecutorWorker
cat -n tensorrt_llm/executor/worker.py | sed -n '67,90p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 1260


🏁 Script executed:

# Verify the concurrent access issue - check if fetch_responses can be called via RPC on GenerationExecutorWorker
rg -n 'start_rpc_server\|fetch_responses' tensorrt_llm/executor/worker.py -B2 -A2

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check RpcWorkerMixin.start_rpc_server to confirm it exposes fetch_responses
rg -n 'start_rpc_server\|def fetch_responses' tensorrt_llm/executor/rpc_worker_mixin.py -B3 -A8

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Search for RPCServer implementation and what methods it exposes
rg -n 'class RPCServer\|def start_rpc_server' tensorrt_llm/executor/ -A15 | head -80

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check what methods RpcWorkerMixin exposes that can be called via RPC
ast-grep outline tensorrt_llm/executor/rpc_worker_mixin.py --view expanded

Repository: NVIDIA/TensorRT-LLM

Length of output: 1090


🏁 Script executed:

# Verify: is fetch_responses actually callable via RPC on a GenerationExecutorWorker with rpc_addr set?
rg -n 'fetch_responses' tensorrt_llm/executor/rpc_worker_mixin.py -B2 -A8

Repository: NVIDIA/TensorRT-LLM

Length of output: 2716


🏁 Script executed:

# Final confirmation: Does GenerationExecutorWorker actually have both code paths active simultaneously?
# Check if start_rpc_server() is ever called with rpc_addr set in practice
rg -n 'GenerationExecutorWorker.*rpc_addr\|rpc_addr=' tensorrt_llm/ -B3 -A3

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Verify the test case to confirm the race condition scenario
cat -n tests/unittest/executor/test_rpc_worker_mixin.py | head -100

Repository: NVIDIA/TensorRT-LLM

Length of output: 2953


🏁 Script executed:

# Verify the actual synchronization mechanism - check if there's any locking around temp_error_responses
rg -n 'Lock\|RLock\|Condition\|Semaphore\|temp_error_responses' tensorrt_llm/executor/base_worker.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Determine if the two code paths can truly run concurrently by checking Queue.get_nowait usage elsewhere
rg -n 'get_nowait\|queue\.Empty' tensorrt_llm/executor/ -B2 -A2

Repository: NVIDIA/TensorRT-LLM

Length of output: 157


🏁 Script executed:

# Check the inheritance chain to verify both code paths exist in a single worker instance
cat -n tensorrt_llm/executor/worker.py | sed -n '37,95p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 2804


🏁 Script executed:

# Verify: is Queue.empty() followed by blocking get() a recognized race condition pattern in this codebase?
rg -n 'empty()' tensorrt_llm/executor/ --type py -B1 -A1

Repository: NVIDIA/TensorRT-LLM

Length of output: 7205


🏁 Script executed:

# Confirm the race condition concern is documented elsewhere in the code
cat -n tensorrt_llm/executor/executor.py | sed -n '310,320p'

Repository: NVIDIA/TensorRT-LLM

Length of output: 748


🏁 Script executed:

# Verify that temp_error_responses.get() without nowait can block indefinitely
python3 -c "
from queue import Queue
import time
import threading

q = Queue()

def reader():
    # Simulate the pattern: check empty() then get()
    if not q.empty():
        item = q.get()  # This will block if empty between check and get
        print(f'Got: {item}')

# Check if Queue.get() blocks when empty
t = threading.Thread(target=reader)
t.daemon = True
t.start()
t.join(timeout=0.5)
if t.is_alive():
    print('RACE CONDITION: get() blocked even though empty() was checked')
else:
    print('No blocking observed')
"

Repository: NVIDIA/TensorRT-LLM

Length of output: 178


Use get_nowait() with exception handling to drain temp_error_responses safely.

process_responses() is called from both AwaitResponseHelper.__call__() (which runs in a ManagedThread) and RpcWorkerMixin.fetch_responses() (which can be called via RPC from concurrent clients). When GenerationExecutorWorker is configured with an RPC server (rpc_addr provided), both paths are active on the same _await_response_helper instance.

The current drain pattern at lines 1125–1126 uses Queue.empty() followed by blocking get(). If one thread checks empty() and finds the queue non-empty, but another thread consumes the item before the first thread calls get(), the first thread blocks indefinitely.

The codebase documents the correct pattern in executor.py:310–320: use get_nowait() and catch queue.Empty. Apply the same approach here.

Current unsafe pattern
while not self.temp_error_responses.empty():
    responses.append(self.temp_error_responses.get())
🤖 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 `@tensorrt_llm/executor/base_worker.py` around lines 1125 - 1126, Update the
temp_error_responses drain in process_responses() to repeatedly call
get_nowait() and catch queue.Empty to terminate the loop. Remove the empty()
check and blocking get() pattern, preserving response collection while remaining
safe for concurrent callers.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64023 [ run ] triggered by Bot. Commit: dd29ae5 Link to invocation

@chuangz0
chuangz0 force-pushed the ray_support_nixl_cache_transceiver branch from dd29ae5 to 760f0b9 Compare August 5, 2026 10:11
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
Signed-off-by: Chuang Zhu <111838961+chuangz0@users.noreply.github.com>
@chuangz0
chuangz0 force-pushed the ray_support_nixl_cache_transceiver branch from 760f0b9 to 7a7ac50 Compare August 5, 2026 10:19

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/integration/defs/examples/test_ray.py (1)

72-197: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add QA list coverage for both Ray serving tests.

Changed tests: test_ray_disaggregated_serving and test_ray_disaggregated_serving_python. No test functions were removed. CI lists cover tp2 on B200 and tp1 on H100. No QA list contains either test. Add both tests to tests/integration/test_lists/qa/llm_function_core.txt or the designated functional QA list. Set LLM_MODELS_ROOT before execution. Coverage verdict: insufficient.

🤖 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 `@tests/integration/defs/examples/test_ray.py` around lines 72 - 197, Add both
test_ray_disaggregated_serving and test_ray_disaggregated_serving_python to the
designated functional QA list, such as
tests/integration/test_lists/qa/llm_function_core.txt. Ensure the QA entries
configure LLM_MODELS_ROOT before execution and cover the existing tp2 B200 and
tp1 H100 CI cases.

Source: Path instructions

🧹 Nitpick comments (1)
cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp (1)

447-455: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Declare immutable local variables as const.

localAgentState, str, and both recvBufferSize variables are not reassigned. Declare them const to meet the C++ coding guideline.

Proposed change
-    AgentState localAgentState{mAgentName, m_Agent->getLocalConnectionInfo()};
+    AgentState const localAgentState{mAgentName, m_Agent->getLocalConnectionInfo()};
 ...
-        auto str = oStream.str();
+        auto const str = oStream.str();
 ...
-            SizeType32 recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
+            SizeType32 const recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
 ...
-            SizeType32 recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
+            SizeType32 const recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);

Also applies to: 464-464, 490-490

🤖 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 `@cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp`
around lines 447 - 455, Update the connection setup code around the
localAgentState serialization flow to declare localAgentState and str as const,
and apply the same const qualification to both recvBufferSize variables at the
referenced locations. Leave reassigned variables unchanged.

Source: Coding guidelines

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

Outside diff comments:
In `@tests/integration/defs/examples/test_ray.py`:
- Around line 72-197: Add both test_ray_disaggregated_serving and
test_ray_disaggregated_serving_python to the designated functional QA list, such
as tests/integration/test_lists/qa/llm_function_core.txt. Ensure the QA entries
configure LLM_MODELS_ROOT before execution and cover the existing tp2 B200 and
tp1 H100 CI cases.

---

Nitpick comments:
In `@cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp`:
- Around line 447-455: Update the connection setup code around the
localAgentState serialization flow to declare localAgentState and str as const,
and apply the same const qualification to both recvBufferSize variables at the
referenced locations. Leave reassigned variables unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d2d0cb22-f5c1-470e-87d5-60ccf9909c1f

📥 Commits

Reviewing files that changed from the base of the PR and between f1f773f and 760f0b9.

📒 Files selected for processing (15)
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.h
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/CMakeLists.txt
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.h
  • examples/ray_orchestrator/disaggregated/disagg_serving_local.sh
  • scripts/build_wheel.py
  • tensorrt_llm/executor/base_worker.py
  • tensorrt_llm/executor/rpc_worker_mixin.py
  • tests/integration/defs/examples/test_ray.py
  • tests/integration/test_lists/test-db/l0_cpu.yml
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
  • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • tests/integration/test_lists/waives.txt
  • tests/unittest/executor/test_rpc_worker_mixin.py
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt
🚧 Files skipped from review as they are similar to previous changes (12)
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.h
  • tests/integration/test_lists/test-db/l0_cpu.yml
  • tensorrt_llm/executor/rpc_worker_mixin.py
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.h
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/CMakeLists.txt
  • tensorrt_llm/executor/base_worker.py
  • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • tests/unittest/executor/test_rpc_worker_mixin.py
  • scripts/build_wheel.py
  • examples/ray_orchestrator/disaggregated/disagg_serving_local.sh
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.cpp

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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)
cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp (2)

447-509: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Declare unchanged local values as const.

localAgentState, str, and both recvBufferSize values do not change after initialization. Declare them const.

As per coding guidelines: “declare unmodified variables as const.”

Proposed change
-    AgentState localAgentState{mAgentName, m_Agent->getLocalConnectionInfo()};
+    AgentState const localAgentState{mAgentName, m_Agent->getLocalConnectionInfo()};
...
-        auto str = oStream.str();
+        auto const str = oStream.str();
...
-            SizeType32 recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
+            SizeType32 const recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
...
-            SizeType32 recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
+            SizeType32 const recvBufferSize = std::accumulate(sizeofBuffer.begin(), sizeofBuffer.end(), 0);
🤖 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 `@cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp`
around lines 447 - 509, Declare the unchanged local values as const in the
agent-state gathering flow: localAgentState, the serialized str value, and both
recvBufferSize declarations. Leave mutable buffers, vectors, and loop variables
unchanged.

Source: Coding guidelines


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

Name the single-process world-size value.

Replace 1 with a named constant. This value defines the collective communication boundary.

As per coding guidelines: “Avoid unexplained literals other than 0, nullptr, true, and false; assign other literals to named constants.”

Proposed change
+    int constexpr kSingleProcessWorldSize = 1;
     AgentState const localAgentState{mAgentName, m_Agent->getLocalConnectionInfo()};
     std::vector<AgentState> agentStates(mWorldSize);
-    if (mWorldSize > 1)
+    if (mWorldSize > kSingleProcessWorldSize)
🤖 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 `@cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp` at
line 449, Update the mWorldSize boundary check in the connection logic to
replace the hardcoded 1 with a named constant that represents the single-process
world size, using the existing connection-related symbols in connection.cpp.
Keep the condition behavior unchanged for multi-process cases, but express the
collective communication cutoff through a descriptive constant instead of an
unexplained literal.

Source: Coding guidelines

🤖 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 `@cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp`:
- Around line 447-509: Declare the unchanged local values as const in the
agent-state gathering flow: localAgentState, the serialized str value, and both
recvBufferSize declarations. Leave mutable buffers, vectors, and loop variables
unchanged.
- Line 449: Update the mWorldSize boundary check in the connection logic to
replace the hardcoded 1 with a named constant that represents the single-process
world size, using the existing connection-related symbols in connection.cpp.
Keep the condition behavior unchanged for multi-process cases, but express the
collective communication cutoff through a descriptive constant instead of an
unexplained literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 03477eb7-c8b3-41e5-8df6-9a031caa31e3

📥 Commits

Reviewing files that changed from the base of the PR and between f1f773f and 7a7ac50.

📒 Files selected for processing (15)
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.h
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/CMakeLists.txt
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.h
  • examples/ray_orchestrator/disaggregated/disagg_serving_local.sh
  • scripts/build_wheel.py
  • tensorrt_llm/executor/base_worker.py
  • tensorrt_llm/executor/rpc_worker_mixin.py
  • tests/integration/defs/examples/test_ray.py
  • tests/integration/test_lists/test-db/l0_cpu.yml
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
  • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • tests/integration/test_lists/waives.txt
  • tests/unittest/executor/test_rpc_worker_mixin.py
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt
🚧 Files skipped from review as they are similar to previous changes (13)
  • tests/integration/test_lists/test-db/l0_dgx_b200.yml
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.h
  • tests/unittest/executor/test_rpc_worker_mixin.py
  • examples/ray_orchestrator/disaggregated/disagg_serving_local.sh
  • tests/integration/test_lists/test-db/l0_cpu.yml
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/CMakeLists.txt
  • tensorrt_llm/executor/rpc_worker_mixin.py
  • scripts/build_wheel.py
  • cpp/tensorrt_llm/executor/cache_transmission/nixl_utils/transferAgent.cpp
  • cpp/tensorrt_llm/executor/cache_transmission/agent_utils/connection.h
  • tests/integration/test_lists/test-db/l0_dgx_h100.yml
  • tests/integration/defs/examples/test_ray.py
  • tensorrt_llm/executor/base_worker.py

@Shixiaowei02

Shixiaowei02 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

The address information exchanged between context and generation servers changes format here without a version marker, so during a rolling upgrade a mixed-version pair would fail to connect, and likewise making the new local-address selection opt-in, since it applies beyond the Ray path.

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64023 [ run ] completed with state SUCCESS. Commit: dd29ae5
/LLM/main/L0_MergeRequest_PR pipeline #51954 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

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.

3 participants