Files
db/heromodels/examples/grid4_nodegroup_example.rs
2025-09-16 14:18:08 +02:00

285 lines
12 KiB
Rust

use heromodels::db::{Collection, Db};
use heromodels::models::grid4::{NodeGroup, PricingPolicy, SLAPolicy};
use heromodels_core::Model;
// Helper function to print nodegroup details
fn print_nodegroup_details(nodegroup: &NodeGroup) {
println!("\n--- NodeGroup Details ---");
println!("ID: {}", nodegroup.get_id());
println!("Farmer ID: {}", nodegroup.farmerid);
println!("Description: {}", nodegroup.description);
println!("Secret: {}", nodegroup.secret);
println!("Compute Slice Pricing (CC): {:.4}", nodegroup.compute_slice_normalized_pricing_cc);
println!("Storage Slice Pricing (CC): {:.4}", nodegroup.storage_slice_normalized_pricing_cc);
println!("Signature Farmer: {}", nodegroup.signature_farmer);
println!("Created At: {}", nodegroup.base_data.created_at);
println!("Modified At: {}", nodegroup.base_data.modified_at);
// Print SLA Policy details
println!(" SLA Policy:");
println!(" Uptime: {}%", nodegroup.slapolicy.sla_uptime);
println!(" Bandwidth: {} Mbit/s", nodegroup.slapolicy.sla_bandwidth_mbit);
println!(" Penalty: {}%", nodegroup.slapolicy.sla_penalty);
// Print Pricing Policy details
println!(" Pricing Policy:");
println!(" Marketplace Year Discounts: {:?}%", nodegroup.pricingpolicy.marketplace_year_discounts);
}
fn main() {
// Create a new DB instance in /tmp/grid4_nodegroups_db, and reset before every run
let db = heromodels::db::hero::OurDB::new("/tmp/grid4_nodegroups_db", true).expect("Can create DB");
println!("Grid4 NodeGroup Models - Basic Usage Example");
println!("===========================================");
// Create SLA policies
let sla_policy_premium = SLAPolicy {
sla_uptime: 99,
sla_bandwidth_mbit: 1000,
sla_penalty: 200,
};
let sla_policy_standard = SLAPolicy {
sla_uptime: 95,
sla_bandwidth_mbit: 100,
sla_penalty: 100,
};
let sla_policy_basic = SLAPolicy {
sla_uptime: 90,
sla_bandwidth_mbit: 50,
sla_penalty: 50,
};
// Create pricing policies
let pricing_policy_aggressive = PricingPolicy {
marketplace_year_discounts: vec![40, 50, 60],
};
let pricing_policy_standard = PricingPolicy {
marketplace_year_discounts: vec![30, 40, 50],
};
let pricing_policy_conservative = PricingPolicy {
marketplace_year_discounts: vec![20, 30, 40],
};
// Create nodegroups with different configurations
// NodeGroup 1 - Premium hosting provider
let nodegroup1 = NodeGroup::new()
.farmerid(501)
.secret("encrypted_boot_secret_premium_abc123".to_string())
.description("Premium hosting with 99% uptime SLA and high-speed connectivity".to_string())
.slapolicy(sla_policy_premium.clone())
.pricingpolicy(pricing_policy_aggressive.clone())
.compute_slice_normalized_pricing_cc(0.0450)
.storage_slice_normalized_pricing_cc(0.0180)
.signature_farmer("farmer_501_premium_signature_xyz789".to_string());
// NodeGroup 2 - Standard business provider
let nodegroup2 = NodeGroup::new()
.farmerid(502)
.secret("encrypted_boot_secret_standard_def456".to_string())
.description("Standard business hosting with reliable performance".to_string())
.slapolicy(sla_policy_standard.clone())
.pricingpolicy(pricing_policy_standard.clone())
.compute_slice_normalized_pricing_cc(0.0350)
.storage_slice_normalized_pricing_cc(0.0150)
.signature_farmer("farmer_502_standard_signature_uvw012".to_string());
// NodeGroup 3 - Budget-friendly provider
let nodegroup3 = NodeGroup::new()
.farmerid(503)
.secret("encrypted_boot_secret_budget_ghi789".to_string())
.description("Cost-effective hosting for development and testing".to_string())
.slapolicy(sla_policy_basic.clone())
.pricingpolicy(pricing_policy_conservative.clone())
.compute_slice_normalized_pricing_cc(0.0250)
.storage_slice_normalized_pricing_cc(0.0120)
.signature_farmer("farmer_503_budget_signature_rst345".to_string());
// NodeGroup 4 - Enterprise provider
let nodegroup4 = NodeGroup::new()
.farmerid(504)
.secret("encrypted_boot_secret_enterprise_jkl012".to_string())
.description("Enterprise-grade infrastructure with maximum reliability".to_string())
.slapolicy(sla_policy_premium.clone())
.pricingpolicy(pricing_policy_standard.clone())
.compute_slice_normalized_pricing_cc(0.0500)
.storage_slice_normalized_pricing_cc(0.0200)
.signature_farmer("farmer_504_enterprise_signature_mno678".to_string());
// Save all nodegroups to database and get their assigned IDs and updated models
let (nodegroup1_id, db_nodegroup1) = db
.collection()
.expect("can open nodegroup collection")
.set(&nodegroup1)
.expect("can set nodegroup");
let (nodegroup2_id, db_nodegroup2) = db
.collection()
.expect("can open nodegroup collection")
.set(&nodegroup2)
.expect("can set nodegroup");
let (nodegroup3_id, db_nodegroup3) = db
.collection()
.expect("can open nodegroup collection")
.set(&nodegroup3)
.expect("can set nodegroup");
let (nodegroup4_id, db_nodegroup4) = db
.collection()
.expect("can open nodegroup collection")
.set(&nodegroup4)
.expect("can set nodegroup");
println!("NodeGroup 1 assigned ID: {}", nodegroup1_id);
println!("NodeGroup 2 assigned ID: {}", nodegroup2_id);
println!("NodeGroup 3 assigned ID: {}", nodegroup3_id);
println!("NodeGroup 4 assigned ID: {}", nodegroup4_id);
// Print all nodegroups retrieved from database
println!("\n--- NodeGroups Retrieved from Database ---");
println!("\n1. Premium hosting provider:");
print_nodegroup_details(&db_nodegroup1);
println!("\n2. Standard business provider:");
print_nodegroup_details(&db_nodegroup2);
println!("\n3. Budget-friendly provider:");
print_nodegroup_details(&db_nodegroup3);
println!("\n4. Enterprise provider:");
print_nodegroup_details(&db_nodegroup4);
// Demonstrate different ways to retrieve nodegroups from the database
// 1. Retrieve by farmer ID index
println!("\n--- Retrieving NodeGroups by Different Methods ---");
println!("\n1. By Farmer ID Index (Farmer 502):");
let farmer_nodegroups = db
.collection::<NodeGroup>()
.expect("can open nodegroup collection")
.get_by_index("farmerid", &502u32)
.expect("can load nodegroups by farmer");
assert_eq!(farmer_nodegroups.len(), 1);
print_nodegroup_details(&farmer_nodegroups[0]);
// 2. Update nodegroup pricing
println!("\n2. Updating NodeGroup Pricing:");
let mut updated_nodegroup = db_nodegroup3.clone();
updated_nodegroup.compute_slice_normalized_pricing_cc = 0.0280;
updated_nodegroup.storage_slice_normalized_pricing_cc = 0.0130;
let (_, price_updated_nodegroup) = db
.collection::<NodeGroup>()
.expect("can open nodegroup collection")
.set(&updated_nodegroup)
.expect("can update nodegroup");
println!("Updated pricing for budget provider:");
println!(" Compute: {:.4} CC", price_updated_nodegroup.compute_slice_normalized_pricing_cc);
println!(" Storage: {:.4} CC", price_updated_nodegroup.storage_slice_normalized_pricing_cc);
// 3. Update SLA policy
println!("\n3. Updating SLA Policy:");
let mut sla_updated_nodegroup = db_nodegroup2.clone();
sla_updated_nodegroup.slapolicy.sla_uptime = 98;
sla_updated_nodegroup.slapolicy.sla_bandwidth_mbit = 500;
let (_, sla_updated_nodegroup) = db
.collection::<NodeGroup>()
.expect("can open nodegroup collection")
.set(&sla_updated_nodegroup)
.expect("can update nodegroup");
println!("Updated SLA policy for standard provider:");
println!(" Uptime: {}%", sla_updated_nodegroup.slapolicy.sla_uptime);
println!(" Bandwidth: {} Mbit/s", sla_updated_nodegroup.slapolicy.sla_bandwidth_mbit);
// Show all nodegroups and calculate analytics
let all_nodegroups = db
.collection::<NodeGroup>()
.expect("can open nodegroup collection")
.get_all()
.expect("can load all nodegroups");
println!("\n--- NodeGroup Analytics ---");
println!("Total NodeGroups: {}", all_nodegroups.len());
// Calculate pricing statistics
let avg_compute_price: f64 = all_nodegroups.iter()
.map(|ng| ng.compute_slice_normalized_pricing_cc)
.sum::<f64>() / all_nodegroups.len() as f64;
let avg_storage_price: f64 = all_nodegroups.iter()
.map(|ng| ng.storage_slice_normalized_pricing_cc)
.sum::<f64>() / all_nodegroups.len() as f64;
let min_compute_price = all_nodegroups.iter()
.map(|ng| ng.compute_slice_normalized_pricing_cc)
.fold(f64::INFINITY, f64::min);
let max_compute_price = all_nodegroups.iter()
.map(|ng| ng.compute_slice_normalized_pricing_cc)
.fold(f64::NEG_INFINITY, f64::max);
println!("Pricing Statistics:");
println!(" Average Compute Price: {:.4} CC", avg_compute_price);
println!(" Average Storage Price: {:.4} CC", avg_storage_price);
println!(" Compute Price Range: {:.4} - {:.4} CC", min_compute_price, max_compute_price);
// Calculate SLA statistics
let avg_uptime: f64 = all_nodegroups.iter()
.map(|ng| ng.slapolicy.sla_uptime as f64)
.sum::<f64>() / all_nodegroups.len() as f64;
let avg_bandwidth: f64 = all_nodegroups.iter()
.map(|ng| ng.slapolicy.sla_bandwidth_mbit as f64)
.sum::<f64>() / all_nodegroups.len() as f64;
let avg_penalty: f64 = all_nodegroups.iter()
.map(|ng| ng.slapolicy.sla_penalty as f64)
.sum::<f64>() / all_nodegroups.len() as f64;
println!("\nSLA Statistics:");
println!(" Average Uptime Guarantee: {:.1}%", avg_uptime);
println!(" Average Bandwidth Guarantee: {:.0} Mbit/s", avg_bandwidth);
println!(" Average Penalty Rate: {:.0}%", avg_penalty);
// Count farmers
let unique_farmers: std::collections::HashSet<_> = all_nodegroups.iter()
.map(|ng| ng.farmerid)
.collect();
println!("\nFarmer Statistics:");
println!(" Unique Farmers: {}", unique_farmers.len());
println!(" NodeGroups per Farmer: {:.1}", all_nodegroups.len() as f64 / unique_farmers.len() as f64);
// Analyze discount policies
let total_discount_tiers: usize = all_nodegroups.iter()
.map(|ng| ng.pricingpolicy.marketplace_year_discounts.len())
.sum();
let avg_discount_tiers: f64 = total_discount_tiers as f64 / all_nodegroups.len() as f64;
println!("\nDiscount Policy Statistics:");
println!(" Average Discount Tiers: {:.1}", avg_discount_tiers);
// Find best value providers (high SLA, low price)
println!("\n--- Provider Rankings ---");
let mut providers_with_scores: Vec<_> = all_nodegroups.iter()
.map(|ng| {
let value_score = (ng.slapolicy.sla_uptime as f64) / ng.compute_slice_normalized_pricing_cc;
(ng, value_score)
})
.collect();
providers_with_scores.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
println!("Best Value Providers (Uptime/Price ratio):");
for (i, (ng, score)) in providers_with_scores.iter().enumerate() {
println!(" {}. Farmer {}: {:.0} ({}% uptime, {:.4} CC)",
i + 1, ng.farmerid, score, ng.slapolicy.sla_uptime, ng.compute_slice_normalized_pricing_cc);
}
println!("\n--- Model Information ---");
println!("NodeGroup DB Prefix: {}", NodeGroup::db_prefix());
}