update grid4 & heroledger models

This commit is contained in:
Timur Gordon
2025-09-16 14:18:08 +02:00
parent cb1fb0f0ec
commit 53e9a2d4f0
31 changed files with 3216 additions and 399 deletions

View File

@@ -0,0 +1,301 @@
use heromodels::db::{Collection, Db};
use heromodels::models::grid4::{Contract, ContractStatus};
use heromodels::models::grid4::contract::contract_index::customer_id;
use heromodels_core::Model;
// Helper function to print contract details
fn print_contract_details(contract: &Contract) {
println!("\n--- Contract Details ---");
println!("ID: {}", contract.get_id());
println!("Customer ID: {}", contract.customer_id);
println!("Compute Slices: {}", contract.compute_slices.len());
println!("Storage Slices: {}", contract.storage_slices.len());
println!("Compute Slice Price: ${:.2}", contract.compute_slice_price);
println!("Storage Slice Price: ${:.2}", contract.storage_slice_price);
println!("Network Slice Price: ${:.2}", contract.network_slice_price);
println!("Status: {:?}", contract.status);
println!("Start Date: {}", contract.start_date);
println!("End Date: {}", contract.end_date);
println!("Billing Period: {:?}", contract.billing_period);
println!("Signature User: {}", contract.signature_user);
println!("Signature Hoster: {}", contract.signature_hoster);
println!("Created At: {}", contract.base_data.created_at);
println!("Modified At: {}", contract.base_data.modified_at);
// Print compute slices details
if !contract.compute_slices.is_empty() {
println!(" Compute Slices:");
for (i, slice) in contract.compute_slices.iter().enumerate() {
println!(" {}. Node: {}, ID: {}, Memory: {:.1}GB, Storage: {:.1}GB, Passmark: {}, vCores: {}",
i + 1, slice.node_id, slice.id, slice.mem_gb, slice.storage_gb, slice.passmark, slice.vcores);
}
}
// Print storage slices details
if !contract.storage_slices.is_empty() {
println!(" Storage Slices:");
for (i, slice) in contract.storage_slices.iter().enumerate() {
println!(" {}. Node: {}, ID: {}, Size: {}GB",
i + 1, slice.node_id, slice.id, slice.storage_size_gb);
}
}
}
fn main() {
// Create a new DB instance in /tmp/grid4_contracts_db, and reset before every run
let db = heromodels::db::hero::OurDB::new("/tmp/grid4_contracts_db", true).expect("Can create DB");
println!("Grid4 Contract Models - Basic Usage Example");
println!("==========================================");
// Create compute slices for contracts
let compute_slice1 = ComputeSliceProvisioned::new()
.node_id(1001)
.id(1)
.mem_gb(2.0)
.storage_gb(20.0)
.passmark(2500)
.vcores(2)
.cpu_oversubscription(150)
.tags("web-server,production".to_string());
let compute_slice2 = ComputeSliceProvisioned::new()
.node_id(1002)
.id(2)
.mem_gb(4.0)
.storage_gb(40.0)
.passmark(5000)
.vcores(4)
.cpu_oversubscription(120)
.tags("database,high-performance".to_string());
let compute_slice3 = ComputeSliceProvisioned::new()
.node_id(1003)
.id(1)
.mem_gb(8.0)
.storage_gb(80.0)
.passmark(10000)
.vcores(8)
.cpu_oversubscription(100)
.tags("ml-training,gpu-enabled".to_string());
// Create storage slices for contracts
let storage_slice1 = StorageSliceProvisioned::new()
.node_id(2001)
.id(1)
.storage_size_gb(100)
.tags("backup,cold-storage".to_string());
let storage_slice2 = StorageSliceProvisioned::new()
.node_id(2002)
.id(2)
.storage_size_gb(500)
.tags("data-lake,analytics".to_string());
let storage_slice3 = StorageSliceProvisioned::new()
.node_id(2003)
.id(1)
.storage_size_gb(1000)
.tags("archive,long-term".to_string());
// Create contracts with different configurations
// Contract 1 - Small web hosting contract
let contract1 = Contract::new()
.customer_id(201)
.add_compute_slice(compute_slice1.clone())
.add_storage_slice(storage_slice1.clone())
.compute_slice_price(0.05)
.storage_slice_price(0.02)
.network_slice_price(0.01)
.status(ContractStatus::Active)
.start_date(1640995200) // 2022-01-01
.end_date(1672531200) // 2023-01-01
.billing_period(BillingPeriod::Monthly)
.signature_user("contract_user_201_abc123".to_string())
.signature_hoster("hoster_node1001_xyz789".to_string());
// Contract 2 - Database hosting contract
let contract2 = Contract::new()
.customer_id(202)
.add_compute_slice(compute_slice2.clone())
.add_storage_slice(storage_slice2.clone())
.compute_slice_price(0.04)
.storage_slice_price(0.015)
.network_slice_price(0.008)
.status(ContractStatus::Active)
.start_date(1640995200)
.end_date(1704067200) // 2024-01-01
.billing_period(BillingPeriod::Yearly)
.signature_user("contract_user_202_def456".to_string())
.signature_hoster("hoster_node1002_uvw123".to_string());
// Contract 3 - ML training contract (paused)
let contract3 = Contract::new()
.customer_id(203)
.add_compute_slice(compute_slice3.clone())
.add_storage_slice(storage_slice3.clone())
.compute_slice_price(0.08)
.storage_slice_price(0.01)
.network_slice_price(0.015)
.status(ContractStatus::Paused)
.start_date(1640995200)
.end_date(1672531200)
.billing_period(BillingPeriod::Hourly)
.signature_user("contract_user_203_ghi789".to_string())
.signature_hoster("hoster_node1003_rst456".to_string());
// Contract 4 - Multi-slice enterprise contract
let contract4 = Contract::new()
.customer_id(204)
.add_compute_slice(compute_slice1.clone())
.add_compute_slice(compute_slice2.clone())
.add_storage_slice(storage_slice1.clone())
.add_storage_slice(storage_slice2.clone())
.compute_slice_price(0.045)
.storage_slice_price(0.018)
.network_slice_price(0.012)
.status(ContractStatus::Active)
.start_date(1640995200)
.end_date(1735689600) // 2025-01-01
.billing_period(BillingPeriod::Monthly)
.signature_user("contract_user_204_jkl012".to_string())
.signature_hoster("hoster_enterprise_mno345".to_string());
// Save all contracts to database and get their assigned IDs and updated models
let (contract1_id, db_contract1) = db
.collection()
.expect("can open contract collection")
.set(&contract1)
.expect("can set contract");
let (contract2_id, db_contract2) = db
.collection()
.expect("can open contract collection")
.set(&contract2)
.expect("can set contract");
let (contract3_id, db_contract3) = db
.collection()
.expect("can open contract collection")
.set(&contract3)
.expect("can set contract");
let (contract4_id, db_contract4) = db
.collection()
.expect("can open contract collection")
.set(&contract4)
.expect("can set contract");
println!("Contract 1 assigned ID: {}", contract1_id);
println!("Contract 2 assigned ID: {}", contract2_id);
println!("Contract 3 assigned ID: {}", contract3_id);
println!("Contract 4 assigned ID: {}", contract4_id);
// Print all contracts retrieved from database
println!("\n--- Contracts Retrieved from Database ---");
println!("\n1. Web hosting contract:");
print_contract_details(&db_contract1);
println!("\n2. Database hosting contract:");
print_contract_details(&db_contract2);
println!("\n3. ML training contract (paused):");
print_contract_details(&db_contract3);
println!("\n4. Enterprise multi-slice contract:");
print_contract_details(&db_contract4);
// Demonstrate different ways to retrieve contracts from the database
// 1. Retrieve by customer ID index
println!("\n--- Retrieving Contracts by Different Methods ---");
println!("\n1. By Customer ID Index (Customer 202):");
let customer_contracts = db
.collection::<Contract>()
.expect("can open contract collection")
.get::<customer_id, _>(&202u32)
.expect("can load contracts by customer");
assert_eq!(customer_contracts.len(), 1);
print_contract_details(&customer_contracts[0]);
// 2. Update contract status
println!("\n2. Resuming Paused Contract:");
let mut updated_contract = db_contract3.clone();
updated_contract.status = ContractStatus::Active;
let (_, resumed_contract) = db
.collection::<Contract>()
.expect("can open contract collection")
.set(&updated_contract)
.expect("can update contract");
println!("Updated contract status to Active:");
print_contract_details(&resumed_contract);
// 3. Cancel a contract
println!("\n3. Cancelling a Contract:");
let mut cancelled_contract = db_contract1.clone();
cancelled_contract.status = ContractStatus::Cancelled;
let (_, final_contract) = db
.collection::<Contract>()
.expect("can open contract collection")
.set(&cancelled_contract)
.expect("can update contract");
println!("Cancelled contract:");
print_contract_details(&final_contract);
// Show remaining active contracts
let all_contracts = db
.collection::<Contract>()
.expect("can open contract collection")
.get_all()
.expect("can load all contracts");
println!("\n--- Contract Analytics ---");
let active_contracts: Vec<_> = all_contracts.iter()
.filter(|c| matches!(c.status, ContractStatus::Active))
.collect();
let paused_contracts: Vec<_> = all_contracts.iter()
.filter(|c| matches!(c.status, ContractStatus::Paused))
.collect();
let cancelled_contracts: Vec<_> = all_contracts.iter()
.filter(|c| matches!(c.status, ContractStatus::Cancelled))
.collect();
println!("Total Contracts: {}", all_contracts.len());
println!("Active Contracts: {}", active_contracts.len());
println!("Paused Contracts: {}", paused_contracts.len());
println!("Cancelled Contracts: {}", cancelled_contracts.len());
// Calculate total provisioned resources
let total_compute_slices: usize = all_contracts.iter().map(|c| c.compute_slices.len()).sum();
let total_storage_slices: usize = all_contracts.iter().map(|c| c.storage_slices.len()).sum();
let total_memory_gb: f64 = all_contracts.iter()
.flat_map(|c| &c.compute_slices)
.map(|s| s.mem_gb)
.sum();
let total_storage_gb: i32 = all_contracts.iter()
.flat_map(|c| &c.storage_slices)
.map(|s| s.storage_size_gb)
.sum();
println!("\nProvisioned Resources:");
println!(" Total Compute Slices: {}", total_compute_slices);
println!(" Total Storage Slices: {}", total_storage_slices);
println!(" Total Memory: {:.1} GB", total_memory_gb);
println!(" Total Storage: {} GB", total_storage_gb);
// Calculate average pricing
let avg_compute_price: f64 = all_contracts.iter().map(|c| c.compute_slice_price).sum::<f64>() / all_contracts.len() as f64;
let avg_storage_price: f64 = all_contracts.iter().map(|c| c.storage_slice_price).sum::<f64>() / all_contracts.len() as f64;
let avg_network_price: f64 = all_contracts.iter().map(|c| c.network_slice_price).sum::<f64>() / all_contracts.len() as f64;
println!("\nAverage Pricing:");
println!(" Compute: ${:.3} per slice", avg_compute_price);
println!(" Storage: ${:.3} per slice", avg_storage_price);
println!(" Network: ${:.3} per slice", avg_network_price);
println!("\n--- Model Information ---");
println!("Contract DB Prefix: {}", Contract::db_prefix());
}