//! 升级实现助手模块 //! //! 提供通用的升级实现辅助函数和宏 /// 为模块生成基础的Upgradeable实现 #[macro_export] macro_rules! impl_upgradeable { ($struct_name:ident, $module_name:expr, $initial_version:expr) => { impl $crate::traits::Upgradeable for $struct_name { fn module_name(&self) -> &str { $module_name } fn current_version(&self) -> $crate::Version { self.version.clone() } fn can_upgrade_to(&self, target: &$crate::Version) -> $crate::Result { if !self.version.can_upgrade_to(target) { return Err($crate::UpgradeError::DowngradeNotAllowed { from: self.version.to_string(), to: target.to_string(), }); } Ok(true) } fn upgrade(&mut self, target: $crate::Version, data: $crate::UpgradeData) -> $crate::Result<()> { // 检查是否可以升级 self.can_upgrade_to(&target)?; // 创建快照 let snapshot = self.create_snapshot()?; // 执行升级 match self.do_upgrade(target.clone(), data) { Ok(_) => { // 记录升级历史 let record = $crate::UpgradeRecord::new( self.upgrade_history.len() as u64 + 1, $module_name.to_string(), self.version.clone(), target.clone(), "system".to_string(), ); let mut record = record; record.mark_success(snapshot.snapshot_id.clone()); self.upgrade_history.push(record); // 更新版本 self.version = target; Ok(()) } Err(e) => { // 升级失败,回滚 self.rollback(snapshot)?; Err(e) } } } fn create_snapshot(&self) -> $crate::Result<$crate::Snapshot> { let state_data = serde_json::to_vec(&self) .map_err(|e| $crate::UpgradeError::SerializationError(e))?; Ok($crate::Snapshot::new( $module_name.to_string(), self.version.clone(), state_data, )) } fn rollback(&mut self, snapshot: $crate::Snapshot) -> $crate::Result<()> { let restored: Self = serde_json::from_slice(&snapshot.state_data) .map_err(|e| $crate::UpgradeError::SerializationError(e))?; *self = restored; Ok(()) } fn upgrade_history(&self) -> Vec<$crate::UpgradeRecord> { self.upgrade_history.clone() } fn validate_state(&self) -> $crate::Result { // 默认实现:总是返回true // 各模块可以override这个方法 Ok(true) } } }; } /// 为模块添加必要的升级字段 #[macro_export] macro_rules! add_upgrade_fields { () => { /// 当前版本 pub version: $crate::Version, /// 升级历史 pub upgrade_history: Vec<$crate::UpgradeRecord>, }; } #[cfg(test)] mod tests { use super::*; use crate::{traits::Upgradeable, UpgradeData, UpgradeRecord, Version}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Debug, Clone, Serialize, Deserialize)] struct TestModule { version: Version, upgrade_history: Vec, data: String, } impl TestModule { fn new() -> Self { Self { version: Version::new(1, 0, 0), upgrade_history: Vec::new(), data: "initial".to_string(), } } fn do_upgrade(&mut self, _target: Version, _data: UpgradeData) -> crate::Result<()> { self.data = "upgraded".to_string(); Ok(()) } } impl_upgradeable!(TestModule, "test-module", Version::new(1, 0, 0)); #[test] fn test_macro_generated_impl() { let mut module = TestModule::new(); assert_eq!(module.module_name(), "test-module"); assert_eq!(module.current_version(), Version::new(1, 0, 0)); let target = Version::new(1, 1, 0); let data = UpgradeData { migration_script: None, config_changes: HashMap::new(), state_migrations: vec![], breaking_changes: vec![], }; assert!(module.upgrade(target.clone(), data).is_ok()); assert_eq!(module.current_version(), target); assert_eq!(module.data, "upgraded"); assert_eq!(module.upgrade_history().len(), 1); } #[test] fn test_snapshot_and_rollback() { let mut module = TestModule::new(); module.data = "original".to_string(); let snapshot = module.create_snapshot().expect("mainnet: handle error"); module.data = "modified".to_string(); assert_eq!(module.data, "modified"); module.rollback(snapshot).expect("mainnet: handle error"); assert_eq!(module.data, "original"); } }