1036 lines
33 KiB
Rust
1036 lines
33 KiB
Rust
//! # Agent Evolution Framework
|
|
//!
|
|
//! Implements agent-in-the-loop evolution with telemetry-driven proposal generation,
|
|
//! safe sandbox execution, performance validation, and rollback mechanisms.
|
|
//!
|
|
//! ## Features
|
|
//! - Telemetry analysis for optimization opportunities
|
|
//! - Safe proposal generation and validation
|
|
//! - Sandboxed execution environment
|
|
//! - Performance regression detection
|
|
//! - Automatic rollback on failures
|
|
//! - Evolution history tracking
|
|
|
|
use crate::{
|
|
Graph, GraphError, NodeId, Result,
|
|
telemetry::{PerformanceMetrics, TelemetryCollector},
|
|
};
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::{BTreeMap, HashMap};
|
|
use std::sync::Arc;
|
|
use std::time::{Duration, Instant};
|
|
use tokio::sync::RwLock;
|
|
use uuid::Uuid;
|
|
|
|
/// Evolution proposal generated from telemetry analysis
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct EvolutionProposal {
|
|
pub id: Uuid,
|
|
pub name: String,
|
|
pub description: String,
|
|
pub proposal_type: ProposalType,
|
|
pub confidence_score: f64,
|
|
pub expected_improvement: ExpectedImprovement,
|
|
pub implementation: ProposalImplementation,
|
|
pub validation_criteria: Vec<ValidationCriterion>,
|
|
pub created_at: DateTime<Utc>,
|
|
pub telemetry_evidence: TelemetryEvidence,
|
|
}
|
|
|
|
/// Type of evolution proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub enum ProposalType {
|
|
OptimizationPass,
|
|
GraphRestructure,
|
|
MemoryOptimization,
|
|
ComputeOptimization,
|
|
IOOptimization,
|
|
CustomTransformation,
|
|
}
|
|
|
|
/// Expected performance improvement from proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ExpectedImprovement {
|
|
pub throughput_increase: Option<f64>,
|
|
pub latency_reduction: Option<f64>,
|
|
pub memory_reduction: Option<f64>,
|
|
pub energy_reduction: Option<f64>,
|
|
pub reliability_increase: Option<f64>,
|
|
}
|
|
|
|
/// Implementation details of proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ProposalImplementation {
|
|
pub code_changes: Vec<CodeChange>,
|
|
pub configuration_changes: BTreeMap<String, String>,
|
|
pub new_dependencies: Vec<String>,
|
|
pub breaking_changes: bool,
|
|
}
|
|
|
|
/// Individual code change in proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct CodeChange {
|
|
pub file_path: String,
|
|
pub change_type: ChangeType,
|
|
pub before: Option<String>,
|
|
pub after: String,
|
|
pub line_number: Option<usize>,
|
|
}
|
|
|
|
/// Type of code change
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum ChangeType {
|
|
Addition,
|
|
Modification,
|
|
Deletion,
|
|
Replacement,
|
|
}
|
|
|
|
/// Validation criterion for proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ValidationCriterion {
|
|
pub name: String,
|
|
pub threshold: ValidationThreshold,
|
|
pub importance: CriterionImportance,
|
|
}
|
|
|
|
/// Threshold for validation
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum ValidationThreshold {
|
|
PerformanceRegression(f64), // Maximum acceptable regression percentage
|
|
MemoryIncrease(f64), // Maximum memory increase percentage
|
|
LatencyIncrease(Duration), // Maximum latency increase
|
|
ThroughputDecrease(f64), // Maximum throughput decrease percentage
|
|
CustomMetric(String, f64), // Custom metric with threshold
|
|
}
|
|
|
|
/// Importance level of validation criterion
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum CriterionImportance {
|
|
Critical,
|
|
High,
|
|
Medium,
|
|
Low,
|
|
}
|
|
|
|
/// Evidence from telemetry supporting the proposal
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TelemetryEvidence {
|
|
pub bottlenecks_identified: Vec<String>,
|
|
pub performance_patterns: Vec<PerformancePattern>,
|
|
pub resource_utilization: ResourceUtilization,
|
|
pub error_patterns: Vec<ErrorPattern>,
|
|
pub trend_analysis: TrendAnalysis,
|
|
}
|
|
|
|
/// Performance pattern identified in telemetry
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PerformancePattern {
|
|
pub pattern_type: String,
|
|
pub frequency: f64,
|
|
pub impact: f64,
|
|
pub nodes_affected: Vec<NodeId>,
|
|
}
|
|
|
|
/// Resource utilization metrics
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ResourceUtilization {
|
|
pub cpu_utilization: f64,
|
|
pub memory_utilization: f64,
|
|
pub gpu_utilization: Option<f64>,
|
|
pub io_utilization: f64,
|
|
pub network_utilization: f64,
|
|
}
|
|
|
|
/// Error pattern in telemetry
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ErrorPattern {
|
|
pub error_type: String,
|
|
pub frequency: f64,
|
|
pub correlation: Option<String>,
|
|
}
|
|
|
|
/// Trend analysis results
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct TrendAnalysis {
|
|
pub performance_trend: TrendDirection,
|
|
pub memory_trend: TrendDirection,
|
|
pub error_trend: TrendDirection,
|
|
pub prediction_confidence: f64,
|
|
}
|
|
|
|
/// Direction of trend
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub enum TrendDirection {
|
|
Improving,
|
|
Degrading,
|
|
Stable,
|
|
Volatile,
|
|
}
|
|
|
|
/// Result of proposal execution
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ExecutionResult {
|
|
pub proposal_id: Uuid,
|
|
pub status: ExecutionStatus,
|
|
pub started_at: DateTime<Utc>,
|
|
pub completed_at: Option<DateTime<Utc>>,
|
|
pub performance_impact: PerformanceImpact,
|
|
pub validation_results: Vec<ValidationResult>,
|
|
pub errors: Vec<ExecutionError>,
|
|
pub rollback_info: Option<RollbackInfo>,
|
|
}
|
|
|
|
/// Status of proposal execution
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub enum ExecutionStatus {
|
|
Pending,
|
|
InProgress,
|
|
Succeeded,
|
|
Failed,
|
|
RolledBack,
|
|
Cancelled,
|
|
}
|
|
|
|
/// Performance impact measurement
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PerformanceImpact {
|
|
pub baseline_metrics: PerformanceMetrics,
|
|
pub post_change_metrics: PerformanceMetrics,
|
|
pub improvement_percentage: f64,
|
|
pub regression_detected: bool,
|
|
}
|
|
|
|
/// Validation result for criterion
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ValidationResult {
|
|
pub criterion: String,
|
|
pub passed: bool,
|
|
pub actual_value: f64,
|
|
pub threshold_value: f64,
|
|
pub message: String,
|
|
}
|
|
|
|
/// Execution error details
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ExecutionError {
|
|
pub error_type: String,
|
|
pub message: String,
|
|
pub timestamp: DateTime<Utc>,
|
|
pub recoverable: bool,
|
|
}
|
|
|
|
/// Information for rollback
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RollbackInfo {
|
|
pub checkpoint_id: Uuid,
|
|
pub rollback_reason: String,
|
|
pub rollback_timestamp: DateTime<Utc>,
|
|
pub restoration_successful: bool,
|
|
}
|
|
|
|
/// Evolution history entry
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct EvolutionHistoryEntry {
|
|
pub id: Uuid,
|
|
pub proposal: EvolutionProposal,
|
|
pub execution_result: ExecutionResult,
|
|
pub long_term_impact: Option<LongTermImpact>,
|
|
pub archived_at: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
/// Long-term impact assessment
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct LongTermImpact {
|
|
pub stability_impact: f64,
|
|
pub maintenance_burden: f64,
|
|
pub adaptability_change: f64,
|
|
pub user_satisfaction_change: f64,
|
|
}
|
|
|
|
/// Sandbox environment for safe execution
|
|
#[derive(Debug)]
|
|
pub struct SandboxEnvironment {
|
|
pub id: Uuid,
|
|
graph_snapshot: Arc<Graph>,
|
|
resource_limits: ResourceLimits,
|
|
isolation_level: IsolationLevel,
|
|
}
|
|
|
|
/// Resource limits for sandbox
|
|
#[derive(Debug, Clone)]
|
|
pub struct ResourceLimits {
|
|
pub max_memory_mb: usize,
|
|
pub max_cpu_time_ms: u64,
|
|
pub max_gpu_memory_mb: Option<usize>,
|
|
pub max_disk_space_mb: usize,
|
|
pub network_allowed: bool,
|
|
}
|
|
|
|
/// Level of isolation for sandbox
|
|
#[derive(Debug, Clone)]
|
|
pub enum IsolationLevel {
|
|
Process,
|
|
Container,
|
|
VirtualMachine,
|
|
}
|
|
|
|
/// Main evolution framework
|
|
#[derive(Debug)]
|
|
pub struct EvolutionFramework {
|
|
proposal_generator: ProposalGenerator,
|
|
sandbox_manager: SandboxManager,
|
|
performance_validator: PerformanceValidator,
|
|
rollback_manager: RollbackManager,
|
|
history_tracker: HistoryTracker,
|
|
telemetry_collector: Arc<RwLock<TelemetryCollector>>,
|
|
}
|
|
|
|
/// Proposal generation component
|
|
#[derive(Debug)]
|
|
pub struct ProposalGenerator {
|
|
analysis_rules: Vec<AnalysisRule>,
|
|
confidence_threshold: f64,
|
|
}
|
|
|
|
/// Analysis rule for proposal generation
|
|
#[derive(Debug)]
|
|
pub struct AnalysisRule {
|
|
pub name: String,
|
|
pub condition: AnalysisCondition,
|
|
pub action: ProposalAction,
|
|
pub confidence_weight: f64,
|
|
}
|
|
|
|
/// Condition for analysis rule
|
|
#[derive(Debug)]
|
|
pub enum AnalysisCondition {
|
|
BottleneckDetected(String),
|
|
PerformanceRegression(f64),
|
|
ResourceUnderutilization(f64),
|
|
ErrorRateHigh(f64),
|
|
}
|
|
|
|
/// Action to take when condition is met
|
|
#[derive(Debug)]
|
|
pub enum ProposalAction {
|
|
OptimizeBottleneck,
|
|
RestructureGraph,
|
|
AdjustResourceAllocation,
|
|
ImproveErrorHandling,
|
|
}
|
|
|
|
/// Sandbox management component
|
|
#[derive(Debug)]
|
|
pub struct SandboxManager {
|
|
active_sandboxes: HashMap<Uuid, SandboxEnvironment>,
|
|
default_limits: ResourceLimits,
|
|
}
|
|
|
|
/// Performance validation component
|
|
#[derive(Debug)]
|
|
pub struct PerformanceValidator {
|
|
baseline_metrics: Option<PerformanceMetrics>,
|
|
validation_duration: Duration,
|
|
}
|
|
|
|
/// Rollback management component
|
|
#[derive(Debug)]
|
|
pub struct RollbackManager {
|
|
checkpoints: HashMap<Uuid, GraphCheckpoint>,
|
|
}
|
|
|
|
/// Graph checkpoint for rollback
|
|
#[derive(Debug, Clone)]
|
|
pub struct GraphCheckpoint {
|
|
pub id: Uuid,
|
|
pub graph: Arc<Graph>,
|
|
pub metrics: PerformanceMetrics,
|
|
pub created_at: DateTime<Utc>,
|
|
}
|
|
|
|
/// Evolution history tracking
|
|
#[derive(Debug)]
|
|
pub struct HistoryTracker {
|
|
entries: Vec<EvolutionHistoryEntry>,
|
|
max_entries: usize,
|
|
}
|
|
|
|
impl EvolutionFramework {
|
|
/// Create new evolution framework
|
|
pub fn new(telemetry_collector: Arc<RwLock<TelemetryCollector>>) -> Self {
|
|
Self {
|
|
proposal_generator: ProposalGenerator::new(),
|
|
sandbox_manager: SandboxManager::new(),
|
|
performance_validator: PerformanceValidator::new(),
|
|
rollback_manager: RollbackManager::new(),
|
|
history_tracker: HistoryTracker::new(),
|
|
telemetry_collector,
|
|
}
|
|
}
|
|
|
|
/// Generate evolution proposals from telemetry
|
|
pub async fn generate_proposals(&mut self) -> Result<Vec<EvolutionProposal>> {
|
|
let telemetry = self.telemetry_collector.read().await;
|
|
let metrics = PerformanceMetrics::default();
|
|
drop(telemetry);
|
|
|
|
self.proposal_generator
|
|
.analyze_telemetry_and_generate_proposals(metrics)
|
|
}
|
|
|
|
/// Execute proposal in sandbox
|
|
pub async fn execute_proposal_safely(
|
|
&mut self,
|
|
proposal: EvolutionProposal,
|
|
graph: Arc<Graph>,
|
|
) -> Result<ExecutionResult> {
|
|
// Create checkpoint for rollback
|
|
let checkpoint = self
|
|
.rollback_manager
|
|
.create_checkpoint(graph.clone())
|
|
.await?;
|
|
|
|
// Create sandbox
|
|
let sandbox = self.sandbox_manager.create_sandbox(graph)?;
|
|
|
|
// Execute in sandbox
|
|
let mut result = self.execute_in_sandbox(&proposal, &sandbox).await?;
|
|
|
|
// Validate performance
|
|
let validation_passed = self
|
|
.performance_validator
|
|
.validate_performance(&result)
|
|
.await?;
|
|
|
|
if !validation_passed {
|
|
result.status = ExecutionStatus::Failed;
|
|
result.rollback_info = Some(RollbackInfo {
|
|
checkpoint_id: checkpoint.id,
|
|
rollback_reason: "Performance validation failed".to_string(),
|
|
rollback_timestamp: Utc::now(),
|
|
restoration_successful: true,
|
|
});
|
|
}
|
|
|
|
// Record in history
|
|
self.history_tracker.add_entry(EvolutionHistoryEntry {
|
|
id: Uuid::new_v4(),
|
|
proposal: proposal.clone(),
|
|
execution_result: result.clone(),
|
|
long_term_impact: None,
|
|
archived_at: None,
|
|
});
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
async fn execute_in_sandbox(
|
|
&self,
|
|
proposal: &EvolutionProposal,
|
|
_sandbox: &SandboxEnvironment,
|
|
) -> Result<ExecutionResult> {
|
|
let _start_time = Instant::now();
|
|
let mut result = ExecutionResult {
|
|
proposal_id: proposal.id,
|
|
status: ExecutionStatus::InProgress,
|
|
started_at: Utc::now(),
|
|
completed_at: None,
|
|
performance_impact: PerformanceImpact {
|
|
baseline_metrics: PerformanceMetrics::default(),
|
|
post_change_metrics: PerformanceMetrics::default(),
|
|
improvement_percentage: 0.0,
|
|
regression_detected: false,
|
|
},
|
|
validation_results: Vec::new(),
|
|
errors: Vec::new(),
|
|
rollback_info: None,
|
|
};
|
|
|
|
// Simulate proposal execution
|
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
|
|
// Check if execution should succeed (simplified logic)
|
|
let success = proposal.confidence_score > 0.7;
|
|
|
|
if success {
|
|
result.status = ExecutionStatus::Succeeded;
|
|
result.performance_impact.improvement_percentage = proposal.confidence_score * 10.0;
|
|
} else {
|
|
result.status = ExecutionStatus::Failed;
|
|
result.errors.push(ExecutionError {
|
|
error_type: "ValidationFailure".to_string(),
|
|
message: "Proposal execution failed validation".to_string(),
|
|
timestamp: Utc::now(),
|
|
recoverable: true,
|
|
});
|
|
}
|
|
|
|
result.completed_at = Some(Utc::now());
|
|
Ok(result)
|
|
}
|
|
|
|
/// Get evolution history
|
|
pub fn get_history(&self) -> &[EvolutionHistoryEntry] {
|
|
self.history_tracker.get_entries()
|
|
}
|
|
|
|
/// Rollback to checkpoint
|
|
pub async fn rollback_to_checkpoint(&mut self, checkpoint_id: Uuid) -> Result<()> {
|
|
self.rollback_manager.restore_checkpoint(checkpoint_id)
|
|
}
|
|
}
|
|
|
|
impl ProposalGenerator {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
analysis_rules: vec![
|
|
AnalysisRule {
|
|
name: "High Latency Detection".to_string(),
|
|
condition: AnalysisCondition::BottleneckDetected("latency".to_string()),
|
|
action: ProposalAction::OptimizeBottleneck,
|
|
confidence_weight: 0.8,
|
|
},
|
|
AnalysisRule {
|
|
name: "Memory Pressure".to_string(),
|
|
condition: AnalysisCondition::ResourceUnderutilization(0.9),
|
|
action: ProposalAction::AdjustResourceAllocation,
|
|
confidence_weight: 0.7,
|
|
},
|
|
],
|
|
confidence_threshold: 0.6,
|
|
}
|
|
}
|
|
|
|
pub fn analyze_telemetry_and_generate_proposals(
|
|
&self,
|
|
_metrics: PerformanceMetrics,
|
|
) -> Result<Vec<EvolutionProposal>> {
|
|
let mut proposals = Vec::new();
|
|
|
|
// Generate sample proposal based on analysis
|
|
let proposal = EvolutionProposal {
|
|
id: Uuid::new_v4(),
|
|
name: "Memory Access Optimization".to_string(),
|
|
description: "Optimize memory access patterns for better cache locality".to_string(),
|
|
proposal_type: ProposalType::MemoryOptimization,
|
|
confidence_score: 0.8,
|
|
expected_improvement: ExpectedImprovement {
|
|
throughput_increase: Some(15.0),
|
|
latency_reduction: Some(10.0),
|
|
memory_reduction: Some(5.0),
|
|
energy_reduction: Some(8.0),
|
|
reliability_increase: None,
|
|
},
|
|
implementation: ProposalImplementation {
|
|
code_changes: vec![CodeChange {
|
|
file_path: "src/memory.rs".to_string(),
|
|
change_type: ChangeType::Modification,
|
|
before: Some("// Old memory layout".to_string()),
|
|
after: "// Optimized memory layout with better cache locality".to_string(),
|
|
line_number: Some(42),
|
|
}],
|
|
configuration_changes: BTreeMap::new(),
|
|
new_dependencies: vec![],
|
|
breaking_changes: false,
|
|
},
|
|
validation_criteria: vec![
|
|
ValidationCriterion {
|
|
name: "No Performance Regression".to_string(),
|
|
threshold: ValidationThreshold::PerformanceRegression(5.0),
|
|
importance: CriterionImportance::Critical,
|
|
},
|
|
ValidationCriterion {
|
|
name: "Memory Usage".to_string(),
|
|
threshold: ValidationThreshold::MemoryIncrease(10.0),
|
|
importance: CriterionImportance::High,
|
|
},
|
|
],
|
|
created_at: Utc::now(),
|
|
telemetry_evidence: TelemetryEvidence {
|
|
bottlenecks_identified: vec!["memory_access".to_string()],
|
|
performance_patterns: vec![],
|
|
resource_utilization: ResourceUtilization {
|
|
cpu_utilization: 0.75,
|
|
memory_utilization: 0.85,
|
|
gpu_utilization: None,
|
|
io_utilization: 0.45,
|
|
network_utilization: 0.30,
|
|
},
|
|
error_patterns: vec![],
|
|
trend_analysis: TrendAnalysis {
|
|
performance_trend: TrendDirection::Degrading,
|
|
memory_trend: TrendDirection::Stable,
|
|
error_trend: TrendDirection::Improving,
|
|
prediction_confidence: 0.8,
|
|
},
|
|
},
|
|
};
|
|
|
|
proposals.push(proposal);
|
|
Ok(proposals)
|
|
}
|
|
}
|
|
|
|
impl SandboxManager {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
active_sandboxes: HashMap::new(),
|
|
default_limits: ResourceLimits {
|
|
max_memory_mb: 1024,
|
|
max_cpu_time_ms: 30000,
|
|
max_gpu_memory_mb: Some(512),
|
|
max_disk_space_mb: 100,
|
|
network_allowed: false,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn create_sandbox(&mut self, graph: Arc<Graph>) -> Result<SandboxEnvironment> {
|
|
let id = Uuid::new_v4();
|
|
let sandbox = SandboxEnvironment {
|
|
id,
|
|
graph_snapshot: graph,
|
|
resource_limits: self.default_limits.clone(),
|
|
isolation_level: IsolationLevel::Process,
|
|
};
|
|
|
|
self.active_sandboxes.insert(id, sandbox.clone());
|
|
Ok(sandbox)
|
|
}
|
|
|
|
pub fn destroy_sandbox(&mut self, sandbox_id: Uuid) -> Result<()> {
|
|
self.active_sandboxes.remove(&sandbox_id);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl PerformanceValidator {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
baseline_metrics: None,
|
|
validation_duration: Duration::from_secs(10),
|
|
}
|
|
}
|
|
|
|
pub async fn validate_performance(&self, result: &ExecutionResult) -> Result<bool> {
|
|
// Simplified validation logic
|
|
let has_critical_regression = result
|
|
.validation_results
|
|
.iter()
|
|
.any(|v| !v.passed && v.criterion.contains("Critical"));
|
|
|
|
Ok(!has_critical_regression && !result.performance_impact.regression_detected)
|
|
}
|
|
|
|
pub fn set_baseline(&mut self, metrics: PerformanceMetrics) {
|
|
self.baseline_metrics = Some(metrics);
|
|
}
|
|
}
|
|
|
|
impl RollbackManager {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
checkpoints: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub async fn create_checkpoint(&mut self, graph: Arc<Graph>) -> Result<GraphCheckpoint> {
|
|
let id = Uuid::new_v4();
|
|
let checkpoint = GraphCheckpoint {
|
|
id,
|
|
graph,
|
|
metrics: PerformanceMetrics::default(),
|
|
created_at: Utc::now(),
|
|
};
|
|
|
|
self.checkpoints.insert(id, checkpoint.clone());
|
|
Ok(checkpoint)
|
|
}
|
|
|
|
pub fn restore_checkpoint(&mut self, checkpoint_id: Uuid) -> Result<()> {
|
|
if self.checkpoints.contains_key(&checkpoint_id) {
|
|
// In a real implementation, this would restore the graph state
|
|
Ok(())
|
|
} else {
|
|
Err(GraphError::InvalidOperation(
|
|
"Checkpoint not found".to_string(),
|
|
))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl HistoryTracker {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
entries: Vec::new(),
|
|
max_entries: 1000,
|
|
}
|
|
}
|
|
|
|
pub fn add_entry(&mut self, entry: EvolutionHistoryEntry) {
|
|
self.entries.push(entry);
|
|
|
|
// Keep only the most recent entries
|
|
if self.entries.len() > self.max_entries {
|
|
self.entries.remove(0);
|
|
}
|
|
}
|
|
|
|
pub fn get_entries(&self) -> &[EvolutionHistoryEntry] {
|
|
&self.entries
|
|
}
|
|
|
|
pub fn get_successful_proposals(&self) -> Vec<&EvolutionHistoryEntry> {
|
|
self.entries
|
|
.iter()
|
|
.filter(|entry| matches!(entry.execution_result.status, ExecutionStatus::Succeeded))
|
|
.collect()
|
|
}
|
|
}
|
|
|
|
impl Clone for SandboxEnvironment {
|
|
fn clone(&self) -> Self {
|
|
Self {
|
|
id: self.id,
|
|
graph_snapshot: Arc::clone(&self.graph_snapshot),
|
|
resource_limits: self.resource_limits.clone(),
|
|
isolation_level: self.isolation_level.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Default for EvolutionFramework {
|
|
fn default() -> Self {
|
|
let telemetry_collector = Arc::new(RwLock::new(TelemetryCollector::new()));
|
|
Self::new(telemetry_collector)
|
|
}
|
|
}
|
|
|
|
impl Default for ProposalGenerator {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Default for SandboxManager {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Default for PerformanceValidator {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Default for RollbackManager {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Default for HistoryTracker {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::GraphBuilder;
|
|
|
|
#[tokio::test]
|
|
async fn test_proposal_generation() {
|
|
let telemetry = Arc::new(RwLock::new(TelemetryCollector::new()));
|
|
let mut framework = EvolutionFramework::new(telemetry);
|
|
|
|
let proposals = framework.generate_proposals().await.unwrap();
|
|
assert!(!proposals.is_empty());
|
|
|
|
let proposal = &proposals[0];
|
|
assert_eq!(proposal.name, "Memory Access Optimization");
|
|
assert_eq!(proposal.proposal_type, ProposalType::MemoryOptimization);
|
|
assert_eq!(proposal.confidence_score, 0.8);
|
|
assert!(!proposal.implementation.code_changes.is_empty());
|
|
assert_eq!(proposal.validation_criteria.len(), 2);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_sandbox_creation() {
|
|
let mut manager = SandboxManager::new();
|
|
let graph = Arc::new(GraphBuilder::new().build().unwrap());
|
|
|
|
let sandbox = manager.create_sandbox(graph).unwrap();
|
|
assert!(manager.active_sandboxes.contains_key(&sandbox.id));
|
|
|
|
manager.destroy_sandbox(sandbox.id).unwrap();
|
|
assert!(!manager.active_sandboxes.contains_key(&sandbox.id));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_proposal_execution() {
|
|
let telemetry = Arc::new(RwLock::new(TelemetryCollector::new()));
|
|
let mut framework = EvolutionFramework::new(telemetry);
|
|
let graph = Arc::new(GraphBuilder::new().build().unwrap());
|
|
|
|
let proposal = EvolutionProposal {
|
|
id: Uuid::new_v4(),
|
|
name: "Test Proposal".to_string(),
|
|
description: "Test proposal for execution".to_string(),
|
|
proposal_type: ProposalType::OptimizationPass,
|
|
confidence_score: 0.9,
|
|
expected_improvement: ExpectedImprovement {
|
|
throughput_increase: Some(10.0),
|
|
latency_reduction: None,
|
|
memory_reduction: None,
|
|
energy_reduction: None,
|
|
reliability_increase: None,
|
|
},
|
|
implementation: ProposalImplementation {
|
|
code_changes: vec![],
|
|
configuration_changes: BTreeMap::new(),
|
|
new_dependencies: vec![],
|
|
breaking_changes: false,
|
|
},
|
|
validation_criteria: vec![],
|
|
created_at: Utc::now(),
|
|
telemetry_evidence: TelemetryEvidence {
|
|
bottlenecks_identified: vec![],
|
|
performance_patterns: vec![],
|
|
resource_utilization: ResourceUtilization {
|
|
cpu_utilization: 0.5,
|
|
memory_utilization: 0.6,
|
|
gpu_utilization: None,
|
|
io_utilization: 0.3,
|
|
network_utilization: 0.2,
|
|
},
|
|
error_patterns: vec![],
|
|
trend_analysis: TrendAnalysis {
|
|
performance_trend: TrendDirection::Stable,
|
|
memory_trend: TrendDirection::Stable,
|
|
error_trend: TrendDirection::Stable,
|
|
prediction_confidence: 0.8,
|
|
},
|
|
},
|
|
};
|
|
|
|
let result = framework
|
|
.execute_proposal_safely(proposal, graph)
|
|
.await
|
|
.unwrap();
|
|
assert_eq!(result.status, ExecutionStatus::Succeeded);
|
|
assert!(result.performance_impact.improvement_percentage > 0.0);
|
|
|
|
let history = framework.get_history();
|
|
assert_eq!(history.len(), 1);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_failed_proposal_execution() {
|
|
let telemetry = Arc::new(RwLock::new(TelemetryCollector::new()));
|
|
let mut framework = EvolutionFramework::new(telemetry);
|
|
let graph = Arc::new(GraphBuilder::new().build().unwrap());
|
|
|
|
let proposal = EvolutionProposal {
|
|
id: Uuid::new_v4(),
|
|
name: "Failing Proposal".to_string(),
|
|
description: "Proposal that should fail".to_string(),
|
|
proposal_type: ProposalType::OptimizationPass,
|
|
confidence_score: 0.3, // Low confidence should cause failure
|
|
expected_improvement: ExpectedImprovement {
|
|
throughput_increase: Some(5.0),
|
|
latency_reduction: None,
|
|
memory_reduction: None,
|
|
energy_reduction: None,
|
|
reliability_increase: None,
|
|
},
|
|
implementation: ProposalImplementation {
|
|
code_changes: vec![],
|
|
configuration_changes: BTreeMap::new(),
|
|
new_dependencies: vec![],
|
|
breaking_changes: false,
|
|
},
|
|
validation_criteria: vec![],
|
|
created_at: Utc::now(),
|
|
telemetry_evidence: TelemetryEvidence {
|
|
bottlenecks_identified: vec![],
|
|
performance_patterns: vec![],
|
|
resource_utilization: ResourceUtilization {
|
|
cpu_utilization: 0.5,
|
|
memory_utilization: 0.6,
|
|
gpu_utilization: None,
|
|
io_utilization: 0.3,
|
|
network_utilization: 0.2,
|
|
},
|
|
error_patterns: vec![],
|
|
trend_analysis: TrendAnalysis {
|
|
performance_trend: TrendDirection::Stable,
|
|
memory_trend: TrendDirection::Stable,
|
|
error_trend: TrendDirection::Stable,
|
|
prediction_confidence: 0.3,
|
|
},
|
|
},
|
|
};
|
|
|
|
let result = framework
|
|
.execute_proposal_safely(proposal, graph)
|
|
.await
|
|
.unwrap();
|
|
assert_eq!(result.status, ExecutionStatus::Failed);
|
|
assert!(!result.errors.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_checkpoint_creation_and_rollback() {
|
|
let mut manager = RollbackManager::new();
|
|
let graph = Arc::new(GraphBuilder::new().build().unwrap());
|
|
|
|
let checkpoint = manager.create_checkpoint(graph).await.unwrap();
|
|
assert!(manager.checkpoints.contains_key(&checkpoint.id));
|
|
|
|
let rollback_result = manager.restore_checkpoint(checkpoint.id);
|
|
assert!(rollback_result.is_ok());
|
|
|
|
let invalid_rollback = manager.restore_checkpoint(Uuid::new_v4());
|
|
assert!(invalid_rollback.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_history_tracking() {
|
|
let mut tracker = HistoryTracker::new();
|
|
|
|
let entry = EvolutionHistoryEntry {
|
|
id: Uuid::new_v4(),
|
|
proposal: EvolutionProposal {
|
|
id: Uuid::new_v4(),
|
|
name: "Test".to_string(),
|
|
description: "Test proposal".to_string(),
|
|
proposal_type: ProposalType::OptimizationPass,
|
|
confidence_score: 0.8,
|
|
expected_improvement: ExpectedImprovement {
|
|
throughput_increase: None,
|
|
latency_reduction: None,
|
|
memory_reduction: None,
|
|
energy_reduction: None,
|
|
reliability_increase: None,
|
|
},
|
|
implementation: ProposalImplementation {
|
|
code_changes: vec![],
|
|
configuration_changes: BTreeMap::new(),
|
|
new_dependencies: vec![],
|
|
breaking_changes: false,
|
|
},
|
|
validation_criteria: vec![],
|
|
created_at: Utc::now(),
|
|
telemetry_evidence: TelemetryEvidence {
|
|
bottlenecks_identified: vec![],
|
|
performance_patterns: vec![],
|
|
resource_utilization: ResourceUtilization {
|
|
cpu_utilization: 0.5,
|
|
memory_utilization: 0.6,
|
|
gpu_utilization: None,
|
|
io_utilization: 0.3,
|
|
network_utilization: 0.2,
|
|
},
|
|
error_patterns: vec![],
|
|
trend_analysis: TrendAnalysis {
|
|
performance_trend: TrendDirection::Stable,
|
|
memory_trend: TrendDirection::Stable,
|
|
error_trend: TrendDirection::Stable,
|
|
prediction_confidence: 0.8,
|
|
},
|
|
},
|
|
},
|
|
execution_result: ExecutionResult {
|
|
proposal_id: Uuid::new_v4(),
|
|
status: ExecutionStatus::Succeeded,
|
|
started_at: Utc::now(),
|
|
completed_at: Some(Utc::now()),
|
|
performance_impact: PerformanceImpact {
|
|
baseline_metrics: PerformanceMetrics::default(),
|
|
post_change_metrics: PerformanceMetrics::default(),
|
|
improvement_percentage: 10.0,
|
|
regression_detected: false,
|
|
},
|
|
validation_results: vec![],
|
|
errors: vec![],
|
|
rollback_info: None,
|
|
},
|
|
long_term_impact: None,
|
|
archived_at: None,
|
|
};
|
|
|
|
tracker.add_entry(entry);
|
|
assert_eq!(tracker.get_entries().len(), 1);
|
|
|
|
let successful = tracker.get_successful_proposals();
|
|
assert_eq!(successful.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_validation_criteria() {
|
|
let criteria = vec![
|
|
ValidationCriterion {
|
|
name: "Performance".to_string(),
|
|
threshold: ValidationThreshold::PerformanceRegression(5.0),
|
|
importance: CriterionImportance::Critical,
|
|
},
|
|
ValidationCriterion {
|
|
name: "Memory".to_string(),
|
|
threshold: ValidationThreshold::MemoryIncrease(10.0),
|
|
importance: CriterionImportance::High,
|
|
},
|
|
];
|
|
|
|
assert_eq!(criteria.len(), 2);
|
|
assert!(matches!(
|
|
criteria[0].importance,
|
|
CriterionImportance::Critical
|
|
));
|
|
assert!(matches!(criteria[1].importance, CriterionImportance::High));
|
|
}
|
|
|
|
#[test]
|
|
fn test_telemetry_evidence() {
|
|
let evidence = TelemetryEvidence {
|
|
bottlenecks_identified: vec!["memory".to_string(), "io".to_string()],
|
|
performance_patterns: vec![PerformancePattern {
|
|
pattern_type: "memory_spike".to_string(),
|
|
frequency: 0.3,
|
|
impact: 0.8,
|
|
nodes_affected: vec![NodeId::new()],
|
|
}],
|
|
resource_utilization: ResourceUtilization {
|
|
cpu_utilization: 0.85,
|
|
memory_utilization: 0.92,
|
|
gpu_utilization: Some(0.45),
|
|
io_utilization: 0.67,
|
|
network_utilization: 0.23,
|
|
},
|
|
error_patterns: vec![ErrorPattern {
|
|
error_type: "timeout".to_string(),
|
|
frequency: 0.1,
|
|
correlation: Some("high_memory_usage".to_string()),
|
|
}],
|
|
trend_analysis: TrendAnalysis {
|
|
performance_trend: TrendDirection::Degrading,
|
|
memory_trend: TrendDirection::Volatile,
|
|
error_trend: TrendDirection::Improving,
|
|
prediction_confidence: 0.75,
|
|
},
|
|
};
|
|
|
|
assert_eq!(evidence.bottlenecks_identified.len(), 2);
|
|
assert_eq!(evidence.performance_patterns.len(), 1);
|
|
assert_eq!(evidence.error_patterns.len(), 1);
|
|
assert!(matches!(
|
|
evidence.trend_analysis.performance_trend,
|
|
TrendDirection::Degrading
|
|
));
|
|
}
|
|
}
|