Skip to content

feat(kv-router): host-supplied inputs for SelectionService parity with the frontend scheduler - #45

Closed
ishandhanani wants to merge 2 commits into
mainfrom
idhanani/up-1-host-hooks
Closed

ishandhanani wants to merge 2 commits into
mainfrom
idhanani/up-1-host-hooks

Conversation

@ishandhanani

@ishandhanani ishandhanani commented Sep 4, 2026 •

Copy link
Copy Markdown
Owner

PR 1 of 9 implementing ai-dynamo#14310 (one SelectionCore for the frontend, the standalone selection service, and the EPP). Base: main.

Fork staging copy of the upstream PR, rebased onto ai-dynamo/main. Replaces fork #8 to #12, which stay open for review history.

Summary

Adds host-supplied scheduling inputs to SelectionCore so the frontend can later embed the same scheduler used by the standalone service. The core gains the frontend's load, eligibility, shared-cache and session inputs without depending on dynamo-runtime.

Implementation

  • SelectionHostHooks supplies the prefill estimator, overload and availability providers, shared KV cache and LoRA filter to each partition.
  • Shared-cache lookup runs alongside primary-index lookup, and structured session context takes precedence over the legacy flat session ID.
  • A common LoRA narrowing helper preserves the caller's allow-set and pinned-worker semantics.
  • A reservation index resolves lifecycle operations by selection ID before falling back to partition scanning for replica-created bookings.
  • Advisory selection reads projected worker load without queue admission or booking; it cannot be used to reserve a worker.
Walkthrough
flowchart LR
  Host[Host inputs] --> Core[SelectionCore]
  Request[Selection request] --> Core
  Core --> Partition[Partition scheduler]
  Partition --> Decision[Worker and projected load]
Loading

Inputs and precedence

prepare_selection_inputs combines indexed overlap, optional shared-cache hits, caller constraints and host eligibility before scheduling. A failed shared-cache lookup logs the failure and proceeds without those hits. LoRA narrowing never widens the caller's allow-set; an allowed pin survives, and an empty narrowing falls back to the caller's set.

SelectionSessionContext carries session_id, parent_session_id, session_final and input_trigger. The trigger maps to the current typed selector contract. KV hints are not a field of this structured session object.

Reservation lifecycle

Both booking paths populate the selection-ID-to-partition index. Prefill completion, output-block updates and free operations consult it first. Partition scanning remains necessary for bookings received from replica peers. A lazily started sweep removes entries after out-of-band booking release; construction itself does not require a Tokio runtime.

Stack boundary

Hooks default to absent, so existing standalone callers retain their prior inputs. This PR supplies the scheduling interface; frontend embedding follows in #47. The hook fields are regrouped into SelectionHost in #49, and reservation-owned affinity leases are added in #53.

Validation

Current stack boundary: 888548e387e778baa5b3df123af9a1547899ea4e; the series is based on Dynamo main ab58558c2dff28f4ff1ea4e219030eac5da3f48f.

  • Passed cargo check -p dynamo-kv-router -p dynamo-llm -p dynamo-ext-proc --no-default-features --features dynamo-kv-router/standalone-selection,dynamo-kv-router/standalone-slot-tracker --all-targets for this stack boundary.
  • The complete series was tested at feat(kv-router): session affinity for the standalone service and EPP #53; its description records the Rust/Python suites, aggregated GPU correctness probes and paired main/final benchmarks. Those end-to-end results apply to the final stack, not to a separate deployment of this intermediate PR.

GitHub CI is not green across this series. Recurring failures are the missing fork Fastchecker runner group, helm-tester image and approval-bot token, plus published-docs composition and an unchanged external documentation link. The local compilation and final-stack validation above are recorded separately from those CI failures.

Stack

# Branch Title Fork PRs it replaces
1 (this PR) idhanani/up-1-host-hooks feat(kv-router): host-supplied inputs for SelectionService parity with the frontend scheduler #8 to #12
2 idhanani/up-2-core-indexing feat(kv-router): approximate, remote, and hint-aware indexing in SelectionService #14 to #16
3 idhanani/up-3-embed-core feat(router): re-host KvRouter scheduling on an embedded selection partition #18, #35
4 idhanani/up-4-delete-kvscheduler refactor(router): delete the runtime-bound KV router scheduler #36
5 idhanani/up-5-policy-source refactor(router): selection policy source, SelectionHost, and dead-flag removal #37
6 idhanani/up-6-membership feat(kv-router): one worker-membership path for frontend and EPP #38
7 idhanani/up-7-kv-index-source refactor(kv-router): one Indexer type and one KV-event ingress for every selection host #39, #41, #43
8 idhanani/up-8-affinity-table refactor(kv-router): one session-affinity implementation for every selection host #42
9 idhanani/up-9-epp-affinity feat(kv-router): session affinity for the standalone service and EPP #44

@github-actions github-actions Bot added feat documentation Improvements or additions to documentation labels Sep 4, 2026
This was referenced Sep 4, 2026
@ishandhanani
ishandhanani force-pushed the idhanani/up-1-host-hooks branch from 7c8494b to 6945918 Compare September 4, 2026 04:00
@ishandhanani
ishandhanani added this pull request to stack #54 September 9, 2026 06:20
…h the frontend scheduler

First half of bringing the standalone selection core to input parity with the
frontend KvRouter so one engine can serve both.

- SelectionHostHooks on SelectionServiceBuilder: prefill-load estimator,
  overloaded-worker exclusion set, hard-availability inclusion set, shared KV
  cache, and LoRA worker filter, applied to every partition scheduler the core
  creates. The standalone service leaves them unset, so its behavior is
  unchanged; an embedding host feeds the same state it passes to KvScheduler.
- Shared-cache hits are queried concurrently with the indexer and reach the
  scorer and custom policies; select requests accept the frontend's structured
  session_context (parent_session_id, session_final, kv_hints, input_trigger),
  with the flat session_id kept as the legacy form.
- LoRA-aware candidate narrowing as a runtime-free LoraWorkerFilter trait with
  the frontend's exact semantics: never widens the allow-set, keeps a pinned
  worker inside it, falls back to the caller's set when narrowing empties it.
- selection_id -> partition index so prefill_complete, free_reservation, and
  add_output_block stop scanning every partition; a lazy sweep drops ids whose
  booking was released out of band.
- Advisory select through select_without_admission (no queue, no booking) with
  the chosen worker's projected load and prefill_busy / decode_busy against the
  conditional-disagg thresholds; admitted responses gain the same two fields.

Tests: providers steer selection through the core; shared-cache hits and every
session field reach the picker; LoRA helper matrix and injected-filter core
test; reservation index population, indexed-first ordering, removal, and
sweep; advisory and admitted responses with and without thresholds.

Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>

This branch had an error being deployed

1 failed deployment
external_collaborator — 888548e3 Deployed Sep 9, 2026 by ishandhanani via ok-to-test #120
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend::vllm deployment::k8s documentation Improvements or additions to documentation feat

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant