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