[Store] Add Mooncake KV Event Publisher for Dynamo-compatible KV events - #2663
[Store] Add Mooncake KV Event Publisher for Dynamo-compatible KV events#2663magicYang1573 wants to merge 1 commit into
Conversation
Mooncake now emits Dynamo-compatible BlockStored/BlockRemoved KV cache events so Dynamo's router can build its prefix index from blocks stored in Mooncake. - Input interface: extend ReplicateConfig with group-level kv_event_metadata (KvBlockEventMetadata / KvBlockComponentSpec) carrying logical-block semantics from the engine; Python bindings included. - Group manifest in MasterService coalesces physical objects into one logical block, publishing exactly one BlockStored on completion and one BlockRemoved on removal, with per-worker dedup. - segment->worker_id registry so each event's worker_id reflects the physical worker (te_endpoint), with optional explicit override. - Output interface: a single ZMQ PUB stream (ZmqKvEventPublisher) emitting the SGLang/vLLM-compatible 3-frame msgpack message; worker_id is carried per event so one centralized stream serves all workers. - Tests for manifest lifecycle, publishing/dedup, worker_id resolution, and a real ZMQ pub/sub roundtrip. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the Mooncake KV Event Publisher, enabling Mooncake to publish Dynamo-compatible KV cache events over ZMQ. The changes include design documentation, C++ models and msgpack serialization for KV events, a ZMQ publisher implementation, integration with the master service to track logical block group manifests, Python bindings, and extensive unit tests. The review feedback suggests clarifying the Python examples in both the English and Chinese design documents to explicitly recommend using None to leave the parent_block_hash field unset.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| meta = KvBlockEventMetadata() | ||
| meta.group_id = "blk-42" | ||
| meta.block_hash = 0x8f3a_0000_0000_0001 | ||
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # leave unset for the root block |
There was a problem hiding this comment.
The comment on this line is a bit confusing. It shows setting a value for parent_block_hash (for a non-root block), but the comment 'leave unset for the root block' could be misinterpreted, for example as setting it to 0.
Since the underlying C++ type is std::optional, the idiomatic Python equivalent for 'unset' is None. To improve clarity, it would be better to explicitly mention this.
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # leave unset for the root block | |
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # For a root block, use `None` to leave it unset. |
| meta = KvBlockEventMetadata() | ||
| meta.group_id = "blk-42" | ||
| meta.block_hash = 0x8f3a_0000_0000_0001 | ||
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # 根 block 则不设置 |
There was a problem hiding this comment.
The comment on this line is a bit confusing. It shows setting a value for parent_block_hash (for a non-root block), but the comment '根 block 则不设置' (don't set for root block) could be misinterpreted, for example as setting it to 0.
Since the underlying C++ type is std::optional, the idiomatic Python equivalent for 'unset' is None. To improve clarity, it would be better to explicitly mention this.
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # 根 block 则不设置 | |
| meta.parent_block_hash = 0x8f3a_0000_0000_0000 # 对于根 block,使用 `None` 来表示不设置。 |
|
This looks like the right semantic follow-up to #2214. Coalescing physical objects behind For Dynamo, I think these should feed the global shared-cache side index keyed by The remaining event-contract follow-up is recovery:
With that contract, Dynamo can use |
|
Closing this PR as superseded by #2214 and ai-dynamo/dynamo#11239. Mooncake #2214 has landed the production KV event publisher, and Dynamo #11239 now consumes the object-level events and maintains the shared-cache index with group_id verification, making the publisher/transport and object-level indexing portions of this PR redundant. If authoritative logical-group lifecycle is still needed, it should be submitted as a focused follow-up on top of #2214, reusing the current wire protocol and covering publisher epoch, snapshot/replay, and HA recovery. |
Description
This PR adds the Mooncake KV Event Publisher: Mooncake can now emit
Dynamo-compatible
BlockStored/BlockRemovedKV cache events so Dynamo'srouter can build its prefix index from KV blocks stored in Mooncake.
There are two interfaces:
ReplicateConfigis extended with group-levelkv_event_metadata(KvBlockEventMetadata/KvBlockComponentSpec) thatcarries the semantic information only the engine knows — sequence
block_hash/parent_block_hash,token_ids,block_size, routingnamespace (
model_name/lora_name/dp_rank), and the physical layout ofthe logical block (
group_ids+expected_components). Python bindings areincluded. When this metadata is absent and no publisher is installed, Mooncake
behavior is unchanged.
manager, it publishes a single ZMQ PUB stream for all workers
(
ZmqKvEventPublisher) using the SGLang/vLLM-compatible 3-frame msgpack wireformat. Each event carries an extra
worker_idfield indicating thephysical node that holds the block, so one stream can serve all workers. A
Mooncake-specific Dynamo adapter (separate repo) parses
worker_id.Internals:
MasterServicecoalesces the physical objects of alogical block and publishes exactly one
BlockStoredon completion and oneBlockRemovedon removal, with per-worker de-duplication.worker_idfrom the owningsegment's transport endpoint (captured at mount time), with an optional
explicit override for deployment/control-plane use.
Design and interface details, plus the remaining SGLang/Dynamo follow-up work,
are documented in:
docs/source/design/kv-event-dynamo/mooncake_kv_event_publisher.mddocs/source/design/kv-event-dynamo/mooncake_kv_event_publisher.zh.mdModule
mooncake-transfer-engine)mooncake-store)mooncake-ep)mooncake-pg)mooncake-integration)mooncake-p2p-store)mooncake-wheel)mooncake-common)mooncake-rl)Type of Change
How Has This Been Tested?
Built and tested in a conda environment with
cppzmq+zeromqinstalled (theZMQ publisher is auto-detected; without ZeroMQ the manifest/encoder still build
and the live ZMQ publisher is omitted).
Test commands:
Test results:
All 149
master_service_testcases pass, including the new tests: manifestlifecycle (create/complete/share/conflict/erase), publishing & de-duplication of
BlockStored/BlockRemoved,worker_idresolution(
SegmentWorkerRegistryCapturesEndpointAtMount,KvEventWorkerIdReflectsSegmentEndpoint,KvEventWorkerIdExplicitOverrideWins),and a real ZMQ pub/sub roundtrip (
ZmqKvEventPublisherRoundTrip) where a SUBsocket receives the 3 frames over TCP and decodes them back into the original
event.
Checklist
./scripts/code_format.shpre-commit run --all-filesand all hooks passAI Assistance Disclosure
AI tooling (Cursor) assisted with implementation, unit tests, and the design
documentation. The submitter has reviewed and is responsible for all changes.