Skip to content

feat(router): support host-controlled affinity time - #15631

Merged
Harrilee merged 11 commits into
mainfrom
harrli/native-affinity-clock-api
Oct 15, 2026
Merged

Harrilee merged 11 commits into
mainfrom
harrli/native-affinity-clock-api

Conversation

@Harrilee

@Harrilee Harrilee commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Allow the existing Rust replay adapter to use Dynamo's native session affinity with simulation time. SessionAffinity::with_manual_clock and advance_clock make acquisition, dispatch commit, lease release and idle TTL follow the host's monotonic clock. Serving keeps its existing runtime clock and background reaper. Manual cleanup retains the native reaper cadence; lookup and acquisition still enforce the exact idle deadline.

The existing sibling-group key function is shared from dynamo-kv-router, with its serving caller retaining identical behavior. The existing PolicyQueue::recheck_all_workers is made public so an external Rust adapter can reconsider blocked worker/DP lanes after capacity changes. Queue ordering and selection algorithms are unchanged.

This PR does not introduce a Python policy class or Rust/Python policy bridge. It adds no package, binding crate or lockfile, and does not change AISimulate dependencies, Python bindings, containers or release/versioning configuration. Existing AISimulate integration remains intact.

Delivery boundaries:

  1. A: this PR provides the small native capabilities independently of AISimulate changes.
  2. B: feat: run AgentX with native Dynamo routing interfaces aisimulate#306 provides neutral dispatch/time callbacks, conversation lineage and CLI selection of the existing optional Dynamo replay plugin. A and B are independent prerequisites, and may be merged in that order without creating a direct AISimulate-to-Dynamo policy import.
  3. After B merges and a matching AISimulate Python wheel and Rust crate nightly is actually published, C: chore(aisimulate): align Dynamo integration with AISim 0.13 #15240 extends the existing Rust replay adapter to consume these hooks and native affinity, pins that real version, and validates the complete YAML/CLI execution path. Full conversation-aware routing is delivered by C, not by A alone.

Four pytest cases use artifact-safe IDs after their previous IDs failed hosted artifact upload. Inputs, assertions and production timeouts remain unchanged.

Validation

  • 10 native affinity tests pass, covering manual time, idle TTL, active leases, abort/invalidation, replica expiry, native cleanup cadence and invalid clock updates.
  • 24 existing native policy-queue tests pass, including blocked-worker rechecks and exact worker-lane behavior.
  • The existing LLM sibling-group key test passes after sharing the helper.
  • Applicable pre-commit hooks and git diff --check pass. Independent diff review found no residual policy bridge, Python binding or dependency/version changes.
  • All seven required checks passed on e11798c8: copyright, DCO, codeowners, backend, Dynamo, pre-merge, and deploy. The full PR workflow completed successfully (77 jobs, no failures); Pre Merge passed too.
  • Pre-refresh 67356490 addressed the review nit by removing one redundant test doc-comment line. The test body, assertions, and runtime implementation are unchanged; rustfmt, applicable pre-commit hooks, and whitespace checks pass. That head's Pre Merge passed; its full PR workflow hit the existing 60-minute EPP image-build timeout. The earlier full-CI result above belongs to e11798c8.
  • The PR is ready for review, with re-review requested from dreamtalen and tedzhouhk. Previous Python-provider/A+B-only results do not validate this revised architecture; current typed-adapter installed CLI qualification belongs to C.

Main conflict refresh (2026-10-12)

Merged main at 33626c578ef387e144449ef8934d043b7a588f05 in 870c62a70d9c97a692c4762ac0880f5167d8c8ac. Main already contains the cancellation response-readiness fix, so its current helper is retained. The native clock, shared sibling-group key and policy-queue API changes are preserved without additional Rust, dependency, binding or release configuration changes.

Local validation: 10 native affinity tests, 24 policy-queue tests, the existing LLM sibling-group key test, two cancellation helper tests and 17 dependency-guard tests pass. Applicable pre-commit hooks, Rust formatting, CODEOWNERS coverage and whitespace checks pass. Hosted CI is being checked against the refreshed head; the historical CI and downstream adapter qualification above do not validate this new merge.

Related: AIC-1817, AIC-1813. #15625 is superseded; #15149 remains closed.

Summary by CodeRabbit

  • New Features
    • Added support for grouping subagent sessions using affinity keys, helping related sessions stay associated with the same backend.
    • Added controllable time for session-affinity tables, enabling predictable expiration and timing behavior in integrations.
    • Exposed a way to refresh worker availability checks before draining queued requests after capacity or eligibility changes.
  • Bug Fixes
    • Improved signaling order for streaming responses in cancellation test utilities.

Signed-off-by: Harry Lee <harrli@nvidia.com>
Signed-off-by: Harry Lee <harrli@nvidia.com>
Signed-off-by: Harry Lee <harrli@nvidia.com>
Signed-off-by: Harry Lee <harrli@nvidia.com>
@devin-ai-integration

devin-ai-integration Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

❌ Dynamo PR CI failed — run 38486322949 (attempt 1) on 1fbfdc6877

Gate checks: ❌ backend-status-check · ✅ deploy-status-check · ✅ dynamo-status-check

Framework Multi-GPU amd64
vLLM ❌ 1

Failure details

1 job failed, before any tests ran: the 2-GPU vLLM runner pod never left Pending, an infrastructure failure; rerunning the failed job is likely enough.

❌ vllm-runtime / 2-GPU Test cuda13.0, amd64: K8s runner pod stuck Pending (Initialize containers)

Job: vllm-runtime / 2-GPU Test cuda13.0, amd64 · Failed step: Initialize containers · Logs: gh run view --job 115607214187 -R ai-dynamo/dynamo --log-failed

Velonix runner admission allowed repository=ai-dynamo/dynamo event=push ref=refs/heads/pull-request/15631
##[group]Run '/home/runner/k8s-novolume/index.js'
##[error]Error: pod failed to come online with error: Error: Pod prod-tester-amd-gpu-2-v2-runner-87fs2-workflow is unhealthy with phase status Pending: {}
##[error]Process completed with exit code 1.
##[error]Executing the custom container implementation failed. Please contact your self hosted runner administrator.

The Kubernetes workflow pod for the self-hosted 2-GPU runner (prod-tester-amd-gpu-2-v2) stayed in Pending and never came online, so the job failed at Initialize containers and no tests ran. This is an infrastructure signature (K8s scheduling / pod startup), not a code failure; a rerun of failed jobs is likely enough.

For agents
{"pr": 15631, "run_id": 38486322949, "run_attempt": 1, "head_sha": "1fbfdc6877774a169f2c7e3cdd57139a5ae14fb6", "failures": [{"job": "vllm-runtime / 2-GPU Test cuda13.0, amd64", "job_id": 115607214187, "failed_step": "Initialize containers", "signature": "pod failed to come online: runner pod unhealthy with phase status Pending", "tests": [], "log_cmd": "gh run view --job 115607214187 -R ai-dynamo/dynamo --log-failed"}]}

Posted automatically by Devin for run 38486322949. Updated on every full-CI run of this PR.

…bridge

Signed-off-by: Harry Lee <harrli@nvidia.com>
@Harrilee Harrilee changed the title feat(router): expose native policies to virtual-time hosts feat(router): support host-controlled affinity time Oct 5, 2026
@Harrilee
Harrilee marked this pull request as ready for review October 5, 2026 19:21
@Harrilee
Harrilee requested review from a team as code owners October 5, 2026 19:21
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: ai-dynamo/dynamo/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: a5ce499a-2ded-4839-b73a-581bd8b90a37
📥 Commits

Reviewing files that changed from the base of the PR and between 519e735 and e11798c.

📒 Files selected for processing (5)
  • lib/kv-router/src/scheduling/policy_queue.rs
  • lib/kv-router/src/services/selection/affinity.rs
  • lib/llm/src/session_affinity/mod.rs
  • tests/fault_tolerance/cancellation/test_utils.py
  • tests/frontend/grpc/test_tensor_parameters.py

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

Walkthrough

The changes add manual-clock support and a shared affinity-key function, expose worker rechecking, and update cancellation and protobuf pin test helpers.

Changes

Session Affinity Clock

Layer / File(s) Summary
Manual-clock setup and affinity exports
lib/kv-router/src/services/selection/affinity.rs, lib/llm/src/session_affinity/mod.rs
SessionAffinity adds optional manual-clock state and a manual-clock constructor. The LLM module re-exports the router’s Hold and subagent_group_affinity_id.
Clock advancement and binding expiry
lib/kv-router/src/services/selection/affinity.rs
Clock advancement validates time updates and collects expired, unleased bindings on the min(ttl, 30s) cadence. Binding operations use the table clock. Tests cover clock advancement, expiry, and invalid time values.

Worker Rechecking

Layer / File(s) Summary
Worker recheck API
lib/kv-router/src/scheduling/policy_queue.rs
PolicyQueue::recheck_all_workers becomes public. Its documentation states that it does not change priorities or queue ordering.

Cancellation Test Signaling

Layer / File(s) Summary
Streaming response readiness
tests/fault_tolerance/cancellation/test_utils.py
The helper assigns the streaming response before signaling response readiness.

Protobuf Pin Test Cases

Layer / File(s) Summary
Pin parameter labels
tests/frontend/grpc/test_tensor_parameters.py
The four invalid protobuf pin cases use explicit IDs. Their values and rejection coverage remain unchanged.

Priority: ➖ Normal

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

Merge Risk: ⚪ Minimal · up to e1179

This change adds opt-in simulated-time support for session affinity and exposes a queue recheck method, without altering serving behavior. No merge-blocking risk was identified.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 43.75% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 32 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed 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 clearly identifies the main change: support for host-controlled affinity time in the router.
Description check Passed The description gives a detailed overview, implementation boundaries, validation results, affected components, and related issue references. It is relevant and sufficiently complete, although it does …
  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@Harrilee
Harrilee enabled auto-merge (squash) October 14, 2026 23:37
@Harrilee
Harrilee merged commit 094aaca into main Oct 15, 2026
123 checks passed
@Harrilee
Harrilee deleted the harrli/native-affinity-clock-api branch October 15, 2026 01:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants