Skip to content

Commit 6252489

Browse files
committed
# Commit Message
refactor: enhance autoscaler tests and liquidity analysis logic ## Changes - Add comprehensive autoscaler tests for memory-based scaling and multiple component types - Refactor liquidity pool analysis to include concentration metrics and risk assessment - Replace generic input processing with specific LP token holder analysis - Implement tiered risk evaluation based on provider concentration levels (largest provider %, top 10%) - Add detailed output including top providers, distribution metrics, and risk notes - Restructure farm account processing logic for improved clarity ## Why These changes improve code maintainability and testability by: - Providing thorough test coverage for autoscaler scaling scenarios - Making liquidity analysis more specific and actionable with clear risk indicators - Enhancing readability through structured branching logic and explicit metrics - Enabling better monitoring of concentration risk in liquidity pools
1 parent ab50b38 commit 6252489

File tree

6 files changed

+14354
-1528
lines changed

6 files changed

+14354
-1528
lines changed

src/utils/isolation/autoscaler.rs

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,4 +910,284 @@ mod tests {
910910
// Even with high CPU, shouldn't scale beyond max
911911
// (This is tested by the scaling logic respecting max_instances)
912912
}
913+
914+
#[tokio::test]
915+
async fn test_autoscaler_memory_based_scaling() {
916+
let registry = Arc::new(ComponentRegistry::new());
917+
let runtime_manager = Arc::new(RuntimeManager::with_defaults());
918+
let network_manager = Arc::new(super::super::NetworkManager::default());
919+
let vsock_manager = Arc::new(
920+
super::super::VsockManager::new(std::env::temp_dir().join("osvm-memory-scale"))
921+
.unwrap(),
922+
);
923+
let hotswap_manager = Arc::new(super::super::HotSwapManager::new(
924+
runtime_manager.clone(),
925+
registry.clone(),
926+
Default::default(),
927+
));
928+
929+
let orchestrator = Arc::new(Orchestrator::new(
930+
registry.clone(),
931+
runtime_manager,
932+
network_manager,
933+
vsock_manager,
934+
hotswap_manager,
935+
Default::default(),
936+
));
937+
938+
let autoscaler = AutoScaler::new(orchestrator, Default::default());
939+
940+
// Policy targeting memory usage
941+
let policy = ScalingPolicy {
942+
component_type: "MemoryIntensive".to_string(),
943+
min_instances: 1,
944+
max_instances: 10,
945+
target_cpu: 0.70,
946+
target_memory: 0.75, // 75% memory target
947+
scale_up_threshold: 0.10,
948+
scale_down_threshold: 0.10,
949+
scale_step: 2, // Scale by 2 at a time
950+
target_rps: None,
951+
};
952+
953+
autoscaler.add_policy(policy).await;
954+
955+
// Register component with high memory usage
956+
let component = Component {
957+
id: ComponentId::new(),
958+
component_type: ComponentType::Service {
959+
name: "MemoryIntensive".to_string(),
960+
},
961+
status: ComponentStatus::Running,
962+
isolation_config: IsolationConfig::default(),
963+
runtime_handle: None,
964+
metadata: Default::default(),
965+
};
966+
967+
let component_id = component.id;
968+
registry.register(component).await.unwrap();
969+
970+
// Report high memory (90% > 75% + 10%)
971+
autoscaler
972+
.update_metrics(ComponentMetrics {
973+
component_id,
974+
cpu_usage: 0.50, // CPU is fine
975+
memory_usage: 0.90, // Memory is high
976+
requests_per_sec: 100.0,
977+
avg_latency_ms: 50.0,
978+
timestamp: std::time::Instant::now(),
979+
})
980+
.await;
981+
982+
// Should trigger scale up based on memory
983+
let result = autoscaler.evaluate_all_policies().await;
984+
assert!(result.is_ok());
985+
}
986+
987+
#[tokio::test]
988+
async fn test_autoscaler_multiple_component_types() {
989+
let registry = Arc::new(ComponentRegistry::new());
990+
let runtime_manager = Arc::new(RuntimeManager::with_defaults());
991+
let network_manager = Arc::new(super::super::NetworkManager::default());
992+
let vsock_manager = Arc::new(
993+
super::super::VsockManager::new(std::env::temp_dir().join("osvm-multi-scale")).unwrap(),
994+
);
995+
let hotswap_manager = Arc::new(super::super::HotSwapManager::new(
996+
runtime_manager.clone(),
997+
registry.clone(),
998+
Default::default(),
999+
));
1000+
1001+
let orchestrator = Arc::new(Orchestrator::new(
1002+
registry.clone(),
1003+
runtime_manager,
1004+
network_manager,
1005+
vsock_manager,
1006+
hotswap_manager,
1007+
Default::default(),
1008+
));
1009+
1010+
let autoscaler = AutoScaler::new(orchestrator, Default::default());
1011+
1012+
// Add policies for different component types
1013+
autoscaler
1014+
.add_policy(ScalingPolicy {
1015+
component_type: "RpcNode".to_string(),
1016+
min_instances: 2,
1017+
max_instances: 10,
1018+
target_cpu: 0.70,
1019+
target_memory: 0.80,
1020+
scale_up_threshold: 0.15,
1021+
scale_down_threshold: 0.20,
1022+
scale_step: 1,
1023+
target_rps: Some(1000.0),
1024+
})
1025+
.await;
1026+
1027+
autoscaler
1028+
.add_policy(ScalingPolicy {
1029+
component_type: "Validator".to_string(),
1030+
min_instances: 1,
1031+
max_instances: 3,
1032+
target_cpu: 0.80,
1033+
target_memory: 0.85,
1034+
scale_up_threshold: 0.10,
1035+
scale_down_threshold: 0.15,
1036+
scale_step: 1,
1037+
target_rps: None,
1038+
})
1039+
.await;
1040+
1041+
// Register components of both types
1042+
let rpc = Component {
1043+
id: ComponentId::new(),
1044+
component_type: ComponentType::RpcNode {
1045+
network: "mainnet".to_string(),
1046+
bind_address: None,
1047+
},
1048+
status: ComponentStatus::Running,
1049+
isolation_config: IsolationConfig::default(),
1050+
runtime_handle: None,
1051+
metadata: Default::default(),
1052+
};
1053+
1054+
let validator = Component {
1055+
id: ComponentId::new(),
1056+
component_type: ComponentType::Validator {
1057+
network: "mainnet".to_string(),
1058+
identity: None,
1059+
},
1060+
status: ComponentStatus::Running,
1061+
isolation_config: IsolationConfig::default(),
1062+
runtime_handle: None,
1063+
metadata: Default::default(),
1064+
};
1065+
1066+
registry.register(rpc.clone()).await.unwrap();
1067+
registry.register(validator.clone()).await.unwrap();
1068+
1069+
// Report metrics for both
1070+
autoscaler
1071+
.update_metrics(ComponentMetrics {
1072+
component_id: rpc.id,
1073+
cpu_usage: 0.60,
1074+
memory_usage: 0.70,
1075+
requests_per_sec: 800.0,
1076+
avg_latency_ms: 45.0,
1077+
timestamp: std::time::Instant::now(),
1078+
})
1079+
.await;
1080+
1081+
autoscaler
1082+
.update_metrics(ComponentMetrics {
1083+
component_id: validator.id,
1084+
cpu_usage: 0.75,
1085+
memory_usage: 0.80,
1086+
requests_per_sec: 0.0,
1087+
avg_latency_ms: 0.0,
1088+
timestamp: std::time::Instant::now(),
1089+
})
1090+
.await;
1091+
1092+
// Evaluate all policies
1093+
let result = autoscaler.evaluate_all_policies().await;
1094+
assert!(result.is_ok());
1095+
}
1096+
1097+
#[test]
1098+
fn test_scaling_decision_logic() {
1099+
let policy = ScalingPolicy {
1100+
component_type: "Test".to_string(),
1101+
min_instances: 1,
1102+
max_instances: 10,
1103+
target_cpu: 0.70,
1104+
target_memory: 0.80,
1105+
scale_up_threshold: 0.10,
1106+
scale_down_threshold: 0.10,
1107+
scale_step: 2,
1108+
target_rps: None,
1109+
};
1110+
1111+
// Test scale up scenario
1112+
assert_eq!(policy.scale_step, 2);
1113+
assert_eq!(policy.target_cpu, 0.70);
1114+
1115+
// Test thresholds
1116+
let high_cpu = 0.85; // 85% > 70% + 15% threshold
1117+
assert!(high_cpu > policy.target_cpu + policy.scale_up_threshold);
1118+
1119+
let low_cpu = 0.45; // 45% < 70% - 20% threshold
1120+
assert!(low_cpu < policy.target_cpu - policy.scale_down_threshold);
1121+
}
1122+
1123+
#[tokio::test]
1124+
async fn test_autoscaler_metrics_aggregation() {
1125+
let registry = Arc::new(ComponentRegistry::new());
1126+
let runtime_manager = Arc::new(RuntimeManager::with_defaults());
1127+
let network_manager = Arc::new(super::super::NetworkManager::default());
1128+
let vsock_manager = Arc::new(
1129+
super::super::VsockManager::new(std::env::temp_dir().join("osvm-metrics-agg")).unwrap(),
1130+
);
1131+
let hotswap_manager = Arc::new(super::super::HotSwapManager::new(
1132+
runtime_manager.clone(),
1133+
registry.clone(),
1134+
Default::default(),
1135+
));
1136+
1137+
let orchestrator = Arc::new(Orchestrator::new(
1138+
registry.clone(),
1139+
runtime_manager,
1140+
network_manager,
1141+
vsock_manager,
1142+
hotswap_manager,
1143+
Default::default(),
1144+
));
1145+
1146+
let autoscaler = AutoScaler::new(orchestrator, Default::default());
1147+
1148+
// Register multiple components and report different metrics
1149+
let component_ids: Vec<_> = (0..5)
1150+
.map(|i| {
1151+
let component = Component {
1152+
id: ComponentId::new(),
1153+
component_type: ComponentType::Service {
1154+
name: format!("service-{}", i),
1155+
},
1156+
status: ComponentStatus::Running,
1157+
isolation_config: IsolationConfig::default(),
1158+
runtime_handle: None,
1159+
metadata: Default::default(),
1160+
};
1161+
let id = component.id;
1162+
futures::executor::block_on(registry.register(component)).unwrap();
1163+
id
1164+
})
1165+
.collect();
1166+
1167+
// Report varying metrics
1168+
for (i, component_id) in component_ids.iter().enumerate() {
1169+
autoscaler
1170+
.update_metrics(ComponentMetrics {
1171+
component_id: *component_id,
1172+
cpu_usage: 0.60 + (i as f64 * 0.05), // 60%, 65%, 70%, 75%, 80%
1173+
memory_usage: 0.50,
1174+
requests_per_sec: 100.0,
1175+
avg_latency_ms: 50.0,
1176+
timestamp: std::time::Instant::now(),
1177+
})
1178+
.await;
1179+
}
1180+
1181+
// Verify all metrics stored
1182+
let metrics = autoscaler.metrics.read().await;
1183+
assert_eq!(metrics.len(), 5);
1184+
1185+
// Verify different CPU values
1186+
let cpu_values: Vec<f64> = component_ids
1187+
.iter()
1188+
.filter_map(|id| metrics.get(id).map(|m| m.cpu_usage))
1189+
.collect();
1190+
assert_eq!(cpu_values.len(), 5);
1191+
assert!(cpu_values[0] < cpu_values[4]); // First < last
1192+
}
9131193
}

0 commit comments

Comments
 (0)