-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[TENT] Bind transport policies to intent type #2848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1016,6 +1016,7 @@ SelectionResult TransferEngineImpl::getTransportType(const Request& request, | |
| ctx.priority_level = | ||
| request.priority; // Use request priority for selection | ||
| ctx.policy_name = request.policy_name; // Optional: bind to specific policy | ||
| ctx.intent_type = request.intent_type; // Business intent policy filter | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While |
||
|
|
||
| if (desc->type == SegmentType::File) { | ||
| // File segment: use selector with empty buffer_transports | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,11 +17,10 @@ | |
| #include "tent/runtime/platform.h" | ||
| #include "tent/thirdparty/nlohmann/json.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <glog/logging.h> | ||
|
|
||
| #include <algorithm> | ||
| #include <cctype> | ||
| #include <cstdint> | ||
| #include <glog/logging.h> | ||
|
|
||
| namespace mooncake { | ||
| namespace tent { | ||
|
|
@@ -63,6 +62,46 @@ static const std::string kMemoryTypeCuda = "cuda"; | |
| static const std::string kMemoryTypeNpu = "npu"; | ||
| static const std::string kMemoryTypeWildcard = "*"; | ||
|
|
||
| static const std::unordered_map<std::string, IntentType> kIntentTypeNameMap = { | ||
| {"intent_unspec", IntentType::INTENT_UNSPEC}, | ||
| {"unspec", IntentType::INTENT_UNSPEC}, | ||
| {"foreground_get", IntentType::FOREGROUND_GET}, | ||
| {"background_prefetch", IntentType::BACKGROUND_PREFETCH}, | ||
| {"migration", IntentType::MIGRATION}, | ||
| {"checkpoint", IntentType::CHECKPOINT}, | ||
| {"weight_loading", IntentType::WEIGHT_LOADING}, | ||
| {"staging_internal", IntentType::STAGING_INTERNAL}, | ||
| }; | ||
|
|
||
| static std::optional<IntentType> parseIntentType(const json& value) { | ||
| if (value.is_string()) { | ||
| auto name = value.get<std::string>(); | ||
| std::transform(name.begin(), name.end(), name.begin(), | ||
| [](unsigned char c) { return std::tolower(c); }); | ||
| auto it = kIntentTypeNameMap.find(name); | ||
| if (it != kIntentTypeNameMap.end()) return it->second; | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| if (value.is_number_unsigned()) { | ||
| const auto raw = value.get<uint64_t>(); | ||
| if (raw <= static_cast<uint64_t>(IntentType::STAGING_INTERNAL)) { | ||
| return static_cast<IntentType>(raw); | ||
| } | ||
| return std::nullopt; | ||
| } | ||
|
|
||
| if (value.is_number_integer()) { | ||
| const auto raw = value.get<int64_t>(); | ||
| if (raw >= static_cast<int64_t>(IntentType::INTENT_UNSPEC) && | ||
| raw <= static_cast<int64_t>(IntentType::STAGING_INTERNAL)) { | ||
| return static_cast<IntentType>(raw); | ||
| } | ||
| } | ||
|
|
||
| return std::nullopt; | ||
| } | ||
|
|
||
| std::string TransportSelector::transportTypeName(TransportType type) { | ||
| auto it = kTransportTypeNames.find(type); | ||
| if (it != kTransportTypeNames.end()) { | ||
|
|
@@ -86,26 +125,34 @@ std::vector<SelectionPolicy> TransportSelector::getDefaultPolicies() { | |
| { | ||
| "file_storage", | ||
| SegmentType::File, | ||
| std::nullopt, // same_machine doesn't matter for file | ||
| std::nullopt, // local_memory_pattern | ||
| std::nullopt, // remote_memory_pattern | ||
| std::nullopt, // min_size | ||
| std::nullopt, // max_size | ||
| std::nullopt, // priority | ||
| {}, // devices (empty = all devices) | ||
| {GDS, IOURING} // File segment priority (original: GDS -> IOURING) | ||
| std::nullopt, // same_machine doesn't matter for file | ||
| std::nullopt, // local_memory_pattern | ||
| std::nullopt, // remote_memory_pattern | ||
| std::nullopt, // min_size | ||
| std::nullopt, // max_size | ||
| std::nullopt, // priority | ||
| {}, // devices (empty = all devices) | ||
| {GDS, IOURING}, // File priority (original: GDS -> IOURING) | ||
| std::nullopt, // service_level | ||
| std::nullopt, // traffic_class | ||
| std::nullopt, // qp_pool | ||
| std::nullopt // intent_type | ||
| }, | ||
| { | ||
| "memory_default", | ||
| SegmentType::Memory, | ||
| std::nullopt, // any machine | ||
| std::nullopt, // any local memory | ||
| std::nullopt, // any remote memory | ||
| std::nullopt, // any size | ||
| std::nullopt, // min_priority | ||
| std::nullopt, // min_size | ||
| std::nullopt, // max_size | ||
| std::nullopt, // priority | ||
| {}, // devices (empty = all devices) | ||
| {} // Empty priority = use buffer_transports order (original | ||
| // behavior) | ||
| {}, // Empty = use buffer_transports order | ||
| std::nullopt, // service_level | ||
| std::nullopt, // traffic_class | ||
| std::nullopt, // qp_pool | ||
| std::nullopt // intent_type | ||
| }, | ||
| }; | ||
| } | ||
|
|
@@ -196,6 +243,19 @@ void TransportSelector::loadPolicies() { | |
| policy.priority = std::nullopt; | ||
| } | ||
|
|
||
| // Parse the optional business-intent filter. An invalid value skips the | ||
| // entire policy instead of turning it into a catch-all rule, which | ||
| // would silently broaden its authorization scope. | ||
| if (policy_json.contains("intent_type")) { | ||
| auto intent = parseIntentType(policy_json["intent_type"]); | ||
| if (!intent.has_value()) { | ||
| LOG(WARNING) | ||
| << "Skip policy " << policy.name << ": invalid intent_type"; | ||
| continue; | ||
| } | ||
| policy.intent_type = *intent; | ||
| } | ||
|
Comment on lines
+249
to
+257
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If a user explicitly configures if (policy_json.contains("intent_type")) {
const auto& val = policy_json["intent_type"];
if (val.is_null()) {
policy.intent_type = std::nullopt;
} else {
auto intent = parseIntentType(val);
if (!intent.has_value()) {
LOG(WARNING)
<< "Skip policy " << policy.name << ": invalid intent_type";
continue;
}
policy.intent_type = *intent;
}
} |
||
|
|
||
| // Parse devices (optional) | ||
| if (policy_json.contains("devices")) { | ||
| for (const auto& device_name : policy_json["devices"]) { | ||
|
|
@@ -351,6 +411,13 @@ bool TransportSelector::matchesPolicy(const SelectionPolicy& policy, | |
| } | ||
| } | ||
|
|
||
| // Policies without an intent filter retain the historical catch-all | ||
| // behavior. Intent-specific policies require an exact match. | ||
| if (policy.intent_type.has_value() && | ||
| context.intent_type != policy.intent_type.value()) { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lookup in
kIntentTypesis case-sensitive. If a user passes--tent_intent_typewith mixed or uppercase characters (e.g.,Foreground_Get), the lookup will fail and trigger a crash viaLOG_ASSERT. Converting the input string to lowercase before performing the lookup makes the command-line interface more robust and user-friendly.