Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions kv_cache_manager/manager/test/cache_manager_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2909,6 +2909,54 @@ TEST_F(CacheManagerTest, InvalidateInstanceMetricsInvokesCallback) {
ASSERT_EQ(1, call_count);
}

TEST_F(CacheManagerTest, TestReportEventBlockSnapshotCurrentlyUnavailable) {
auto expected_reg = std::pair<ErrorCode, std::string>(EC_OK, default_storage_configs);
ASSERT_EQ(expected_reg,
cache_manager_->RegisterInstance(request_context_.get(),
"default",
"test_instance",
64,
createLocationSpecInfos(),
createModelDeployment(),
std::vector<LocationSpecGroup>()));

auto metrics_registry = cache_manager_->metrics_registry_;
auto vineyard_backend = std::make_shared<VineyardBackend>(metrics_registry);
StorageConfig v6d_config;
v6d_config.set_global_unique_name("vineyard_default");
v6d_config.set_type(DataStorageType::DATA_STORAGE_TYPE_VINEYARD);
v6d_config.set_storage_spec(std::make_shared<VineyardStorageSpec>());
ASSERT_EQ(EC_OK, vineyard_backend->Open(v6d_config, "test_trace"));

auto dsm = registry_manager_->data_storage_manager_;
dsm->storage_map_["vineyard_default"] = vineyard_backend;
registry_manager_->instance_group_configs_["default"]->set_event_reporting_storage_candidates({"vineyard_default"});

proto::meta::ReportEventRequest req;
req.set_instance_id("test_instance");
req.set_host_ip_port("192.168.1.10:8080");
req.set_storage_type(proto::meta::ST_VINEYARD);

auto *ev = req.add_events();
ev->set_event_type(proto::meta::EVENT_BLOCK_SNAPSHOT);
auto *snapshot = ev->mutable_block_snapshot();
snapshot->set_medium("mem");
auto *block = snapshot->add_blocks();
block->set_block_key("123");
auto *spec = block->add_specs();
spec->set_name("tp0");
spec->set_uri("vineyard://192.168.1.10:8080/mem/123");

proto::meta::ReportEventResponse resp;
EXPECT_EQ(EC_PARTIAL_OK, cache_manager_->ReportEvent(request_context_.get(), &req, &resp));
ASSERT_EQ(proto::meta::INTERNAL_ERROR, resp.header().status().code());
ASSERT_EQ(1, resp.item_results_size());
EXPECT_EQ(proto::meta::INVALID_ARGUMENT, resp.item_results(0));

dsm->storage_map_.erase("vineyard_default");
registry_manager_->instance_group_configs_["default"]->set_event_reporting_storage_candidates({});
}

// =============================================================
// GetCacheLocationsByBackend with backend_selectors
// =============================================================
Expand Down
62 changes: 43 additions & 19 deletions kv_cache_manager/protocol/protobuf/meta_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -46,49 +46,73 @@ enum StorageType {
ST_VINEYARD = 7;
}

// ---- V6D event reporting ----
// ---- Cache event reporting ----
//
// ReportEvent is the ingestion API used by cache subscribers. A subscriber
// normalizes engine-specific cache signals (for example RTP-LLM full cache
// snapshots or vLLM KV events) into block-level mutations on one storage
// system. `storage_type` names that large storage/cache system; `medium`
// identifies one diffable cache namespace under the reporter host; LocationSpec
// describes where each cache component of the block lives. KVCM currently
// matches only full-attention specs and ignores mamba-state specs by
// LocationSpec.name.

enum ReportEventType {
EVENT_UNSPECIFIED = 0;
EVENT_NODE_REGISTER = 1; // V6D node starts up and registers with KVCM
EVENT_BLOCK_ADD = 2; // V6D stored a new block locally
EVENT_BLOCK_DELETE = 3; // V6D deleted a block locally
EVENT_HOST_DOWN = 4; // V6D node is going down (graceful or detected)
EVENT_HEARTBEAT = 5; // V6D periodic heartbeat
EVENT_NODE_REGISTER = 1; // Reporter node starts up and registers with KVCM
EVENT_BLOCK_ADD = 2; // Reporter stored a block in one location
EVENT_BLOCK_DELETE = 3; // Reporter removed a block from one location
EVENT_HOST_DOWN = 4; // Reporter node is going down (graceful or detected)
EVENT_HEARTBEAT = 5; // Reporter periodic heartbeat
EVENT_BLOCK_SNAPSHOT = 6; // Reporter sends the full block set for one host/medium
}

message NodeRegisterParams {
message NodeRegisterEventParams {
repeated string mediums = 1; // mediums supported by the node, e.g. ["mem","disk"]
}

message BlockAddParams {
message BlockAddEventParams {
Comment on lines +70 to +74

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve generated ReportEvent message type names

Renaming the existing protobuf messages changes the generated API surface even though the field numbers and oneof accessors stay wire-compatible. Downstream ReportEvent producers that construct or annotate NodeRegisterParams, BlockAddParams, etc. from the current schema will fail to compile/import after regenerating stubs because those public types have been replaced by *EventParams; keeping the old message names while adding the snapshot types avoids a source-breaking schema-only change.

Useful? React with 👍 / 👎.

string block_key = 1; // int64 as string
string uri = 2; // deprecated, use specs instead
string medium = 3; // e.g. "mem"/"disk"/"ssd"/"hbm"
string medium = 3; // cache tier/namespace, e.g. "mem", "disk", "gpu", "hbm"
repeated LocationSpec specs = 4;
}

message BlockDeleteParams {
message BlockDeleteEventParams {
string block_key = 1;
string medium = 2;
string medium = 2; // cache tier/namespace, e.g. "mem", "disk", "gpu", "hbm"
// Optional. When set, KVCM applies the delete only if these component names
// contain a full-attention spec; mamba-state-only deletes are ignored.
repeated string spec_names = 3;
Comment on lines +84 to +86

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor spec_names before deleting block locations

When a reporter sends EVENT_BLOCK_DELETE with spec_names set to only mamba-state names, this new schema promises that KVCM will ignore the delete, but the current ReportEvent path never reads p.spec_names() and always queues BuildLocationId(p.medium(), host_ip_port) for deletion in cache_manager.cc:1619-1620. That removes the entire host/medium location, including any full-attention specs previously added under the same location, so clients following the newly advertised field can accidentally evict valid KV cache metadata.

Useful? React with 👍 / 👎.

}

message HostDownParams {
message BlockSnapshotItem {
string block_key = 1;
repeated LocationSpec specs = 2;
}

message BlockSnapshotEventParams {
string medium = 1; // cache tier/namespace, e.g. "mem", "disk", "gpu", "hbm"
repeated BlockSnapshotItem blocks = 2;
}

message HostDownEventParams {
}

message HeartbeatParams {
message HeartbeatEventParams {
// KVCM only refreshes last_heartbeat; system_status is opaque observability data
map<string, string> system_status = 1;
}

message EventItem {
ReportEventType event_type = 1;
oneof event_params {
NodeRegisterParams node_register = 2;
BlockAddParams block_add = 3;
BlockDeleteParams block_delete = 4;
HostDownParams host_down = 5;
HeartbeatParams heartbeat = 6;
NodeRegisterEventParams node_register = 2;
BlockAddEventParams block_add = 3;
BlockDeleteEventParams block_delete = 4;
HostDownEventParams host_down = 5;
HeartbeatEventParams heartbeat = 6;
BlockSnapshotEventParams block_snapshot = 7;
}
}

Expand All @@ -97,7 +121,7 @@ message ReportEventRequest {
string instance_id = 2;
string host_ip_port = 3;
repeated EventItem events = 4;
StorageType storage_type = 5; // required: declares the reporter's storage type
StorageType storage_type = 5; // required: declares the reporter's storage/cache system
}

message ReportEventResponse {
Expand Down
Loading