1 pub mod dep_graph; 2 pub mod service_executor; 3 4 use crate::{ 5 error::runtime_error::{RuntimeError, RuntimeErrorType}, 6 manager::UnitManager, 7 unit::UnitState, 8 }; 9 10 #[allow(dead_code)] 11 #[derive(Debug, Clone, Copy)] 12 pub enum ExitStatus { 13 Success, // 成功退出 14 Failure, // 启动失败 15 Abnormal, // 异常退出 16 Abort, // 显式退出 17 Watchdog, // 超时检测 18 } 19 20 impl ExitStatus { 21 /// ## 从错误码获得退出状态 22 /// 23 /// 注意,该方法只会返回Success(exit_code == 0)和Abnormal(exit_code != 0)两种状态 24 /// 其他DragonReach定义的退出状态需要手动指定 25 /// 26 /// ### return Success(exit_code == 0)、Abnormal(exit_code != 0) 27 pub fn from_exit_code(exit_code: i32) -> Self { 28 match exit_code { 29 0 => return Self::Success, 30 _ => return Self::Abnormal, 31 } 32 } 33 } 34 35 //Unit的全局执行器 36 pub struct Executor; 37 38 impl Executor { 39 /// ## 全局执行器入口,将会进行启动检测以及循环依赖检测 40 pub fn exec(unit_id: usize) -> Result<(), RuntimeError> { 41 // TODO: 添加超时检测,这个工作应该在线程执行 42 43 { 44 // 设置Unit状态为正在启动 45 // TODO: 目前单线程工作这样设置是无意义的 46 UnitManager::get_unit_with_id(&unit_id) 47 .unwrap() 48 .lock() 49 .unwrap() 50 .unit_base_mut() 51 .set_state(UnitState::Activating); 52 } 53 match Self::exec_(unit_id) { 54 Ok(_) => { 55 UnitManager::get_unit_with_id(&unit_id) 56 .unwrap() 57 .lock() 58 .unwrap() 59 .unit_base_mut() 60 .set_state(UnitState::Active); 61 Ok(()) 62 } 63 Err(e) => { 64 let mutex = UnitManager::get_unit_with_id(&unit_id).unwrap(); 65 let mut unit = mutex.lock().unwrap(); 66 67 // 启动失败时启动onfailure项目 68 for id in unit.unit_base().unit_part().on_failure() { 69 // TODO: 待日志库开发后,这里的错误处理应该是打印日志 70 let _ = Executor::exec(*id); 71 } 72 73 unit.unit_base_mut().set_state(UnitState::Failed); 74 unit.after_exit(ExitStatus::Failure); 75 return Err(e); 76 } 77 } 78 } 79 pub fn exec_(unit_id: usize) -> Result<(), RuntimeError> { 80 // TODO: 目前的启动逻辑还是串行启动,后续需更改为并行启动某些项 81 82 let unit = match UnitManager::get_unit_with_id(&unit_id) { 83 Some(s) => s, 84 None => { 85 return Err(RuntimeError::new(RuntimeErrorType::FileNotFound)); 86 } 87 }; 88 89 let mut unit = unit.lock().unwrap(); 90 91 //TODO: 优化此处,解析时也用到了拓扑排序,尝试使用那次拓扑排序的结果 92 // 此处不需要再次拓扑排序,在parse时已经确定不会出现循环依赖,现在仅需按照启动流程启动即可 93 // let mut graph = DepGraph::construct_graph(&unit); 94 // let sort_ret = graph.topological_sort()?; 95 96 // 优先启动After 97 for u in unit.unit_base().unit_part().after() { 98 if UnitManager::is_running_unit(&u) { 99 continue; 100 } 101 let mutex = UnitManager::get_unit_with_id(&u).unwrap(); 102 let mut after = mutex.lock().unwrap(); 103 after.run()?; 104 } 105 106 // 启动Requires 107 for u in unit.unit_base().unit_part().requires() { 108 if UnitManager::is_running_unit(&u) { 109 continue; 110 } 111 let mutex = UnitManager::get_unit_with_id(&u).unwrap(); 112 let mut after = mutex.lock().unwrap(); 113 after.run()?; 114 } 115 116 // 启动binds 117 for u in unit.unit_base().unit_part().binds_to() { 118 if UnitManager::is_running_unit(&u) { 119 continue; 120 } 121 let mutex = UnitManager::get_unit_with_id(&u).unwrap(); 122 let mut after = mutex.lock().unwrap(); 123 after.run()?; 124 } 125 126 // 启动Wants 127 for u in unit.unit_base().unit_part().wants() { 128 if UnitManager::is_running_unit(&u) { 129 continue; 130 } 131 let mutex = UnitManager::get_unit_with_id(&u).unwrap(); 132 let mut after = mutex.lock().unwrap(); 133 let _ = after.run(); 134 } 135 136 // 启动自身 137 unit.run()?; 138 return Ok(()); 139 } 140 141 pub fn restart(id: usize) -> Result<(), RuntimeError> { 142 if let Some(unit) = UnitManager::get_unit_with_id(&id) { 143 unit.lock().unwrap().restart()?; 144 } 145 Ok(()) 146 } 147 } 148