Describe the bug
When an engine clears its prefix cache — /reset_prefix_cache, OOM-driven reset, or /sleep level>=1 — it wipes the cache and enqueues AllBlocksCleared. We don't act on it: handleAllBlocksCleared is a no-op (pkg/kvevent/handler.go), and the only caller of RemovePrefix is pod unsubscribe, which doesn't fire here (the pod stays Running, /health still returns 200). So stale entries linger, and because the prefix router prefers the pod with the most matching blocks, it actively routes prefix traffic to the pod whose cache was just wiped — a cold miss.
The event alone isn't a reliable fix: vLLM publishes queued KV events only from inside a scheduler step (update_from_output), so an idle/sleeping engine may never flush AllBlocksCleared, and ZMQ delivery is lossy.
Steps to Reproduce
- Two replicas with the kv-event prefix router; warm a shared prefix on pod A.
POST /reset_prefix_cache on pod A (or /sleep?level=1).
- Send the same prefix again → still routed to A, now a cold miss.
Expected behavior
handleAllBlocksCleared calls RemovePrefix(model, loraID, podKey) (already on the SyncIndexer interface).
- A reconcile against the scraped
vllm:engine_sleep_state metric backstops dropped events (purge entries for pods reporting non-awake).
- When AIBrix drives sleep itself (separate sleep-mode RFC), it should also purge synchronously on
/sleep — tracked there.
Environment
AIBrix: main · vLLM: main (kv-events enabled).
Describe the bug
When an engine clears its prefix cache —
/reset_prefix_cache, OOM-driven reset, or/sleep level>=1— it wipes the cache and enqueuesAllBlocksCleared. We don't act on it:handleAllBlocksClearedis a no-op (pkg/kvevent/handler.go), and the only caller ofRemovePrefixis pod unsubscribe, which doesn't fire here (the pod staysRunning,/healthstill returns 200). So stale entries linger, and because the prefix router prefers the pod with the most matching blocks, it actively routes prefix traffic to the pod whose cache was just wiped — a cold miss.The event alone isn't a reliable fix: vLLM publishes queued KV events only from inside a scheduler step (
update_from_output), so an idle/sleeping engine may never flushAllBlocksCleared, and ZMQ delivery is lossy.Steps to Reproduce
POST /reset_prefix_cacheon pod A (or/sleep?level=1).Expected behavior
handleAllBlocksClearedcallsRemovePrefix(model, loraID, podKey)(already on theSyncIndexerinterface).vllm:engine_sleep_statemetric backstops dropped events (purge entries for pods reporting non-awake)./sleep— tracked there.Environment
AIBrix: main · vLLM: main (kv-events enabled).