xref: /DragonReach/src/executor/mod.rs (revision d70ac4ed6bb8b5d8d8428c184b072058ec9266d2)
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 
102             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
103             let mut after = mutex.lock().unwrap();
104             after.run()?;
105         }
106 
107         // 启动Requires
108         for u in unit.unit_base().unit_part().requires() {
109             if UnitManager::is_running_unit(&u) {
110                 continue;
111             }
112             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
113             let mut after = mutex.lock().unwrap();
114             after.run()?;
115         }
116 
117         // 启动binds
118         for u in unit.unit_base().unit_part().binds_to() {
119             if UnitManager::is_running_unit(&u) {
120                 continue;
121             }
122             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
123             let mut after = mutex.lock().unwrap();
124             after.run()?;
125         }
126 
127         // 启动Wants
128         for u in unit.unit_base().unit_part().wants() {
129             if UnitManager::is_running_unit(&u) {
130                 continue;
131             }
132             let mutex = UnitManager::get_unit_with_id(&u).unwrap();
133             let mut after = mutex.lock().unwrap();
134             let _ = after.run();
135         }
136 
137         // 启动自身
138         unit.run()?;
139         return Ok(());
140     }
141 
142     pub fn restart(id: usize) -> Result<(), RuntimeError> {
143         if let Some(unit) = UnitManager::get_unit_with_id(&id) {
144             unit.lock().unwrap().restart()?;
145         }
146         Ok(())
147     }
148 }
149