1use super::command::{Cli, EmptyCommand};
2use super::component::DynComponent;
3use super::component_factory::ComponentFactoryManager;
4use super::signal::shutdown_signal;
5use super::version::GLOBAL_VERSION_PRINTER;
6use anyhow::{Context, Result};
7use clap::{Parser, Subcommand};
8use config::{Config, File};
9use std::any::TypeId;
10use std::collections::HashMap;
11use std::fs;
12use std::future::Future;
13use std::marker::PhantomData;
14use std::path::PathBuf;
15use std::pin::Pin;
16use std::sync::{Arc, Mutex as StdMutex, RwLock as StdRwLock};
17use std::time::Duration;
18use tokio::sync::RwLock;
19use tokio::time::sleep;
20use tracing::info;
21
22#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct ComponentKey {
25 pub type_id: TypeId,
26 pub label: String,
27}
28
29#[derive(Default)]
31pub struct ApplicationInner {
32 config: RwLock<Config>,
33 components: RwLock<HashMap<ComponentKey, Arc<dyn DynComponent>>>,
34 wait_signal: StdRwLock<bool>,
35}
36
37impl ApplicationInner {
38 pub async fn get_component<C: DynComponent + 'static>(&self, label: Option<&str>) -> Option<Arc<C>> {
40 let type_id = TypeId::of::<C>();
41 let label = label.unwrap_or("default").to_string();
42 let key = ComponentKey { type_id, label };
43
44 let components = self.components.read().await;
45 components
46 .get(&key)
47 .cloned()
48 .and_then(|arc| Arc::downcast(arc).ok())
50 }
51
52 pub async fn must_get_component<C: DynComponent + 'static>(&self, label: Option<&str>) -> Result<Arc<C>> {
54 let type_name = std::any::type_name::<C>();
55 let label_str = label.unwrap_or("default");
56
57 self.get_component(label).await.ok_or_else(|| {
58 anyhow::anyhow!("component not found or type mismatch: type={}, label={}", type_name, label_str)
59 })
60 }
61
62 pub async fn config(&self) -> tokio::sync::RwLockReadGuard<'_, Config> {
64 self.config.read().await
65 }
66
67 pub async fn config_mut(&self) -> tokio::sync::RwLockWriteGuard<'_, Config> {
69 self.config.write().await
70 }
71
72 pub fn set_wait_signal(&self, wait: bool) {
73 let mut wait_signal = self.wait_signal.write().expect("Failed to write wait_signal RwLock");
74 *wait_signal = wait;
75 }
76}
77
78#[derive(Debug, Clone)]
80pub enum InitStrategy {
81 All,
83 None,
85 Only(Vec<ComponentKey>),
87 Deny(Vec<ComponentKey>),
89}
90
91type HandlerFuture = Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>>;
93
94type CommandHandler<T> = Box<
96 dyn Fn(T, Arc<ApplicationInner>, Arc<ComponentFactoryManager>) -> (InitStrategy, HandlerFuture)
97 + Send
98 + Sync
99 + 'static,
100>;
101
102type DefaultHandler = Box<
104 dyn Fn(Arc<ApplicationInner>, Arc<ComponentFactoryManager>) -> (InitStrategy, HandlerFuture)
105 + Send
106 + Sync
107 + 'static,
108>;
109
110pub struct App<T: Subcommand + Clone + 'static = EmptyCommand> {
112 default_handler: StdMutex<Option<DefaultHandler>>,
113 command_handler: StdMutex<Option<CommandHandler<T>>>,
114 component_factories: Arc<ComponentFactoryManager>,
115 inner: Arc<ApplicationInner>,
116 phantom: PhantomData<T>,
117}
118
119impl<T: Subcommand + Clone + 'static> App<T> {
120 pub fn new() -> Self {
122 Self {
123 command_handler: StdMutex::new(None),
124 component_factories: Arc::new(ComponentFactoryManager::new()),
125 inner: Arc::new(ApplicationInner { wait_signal: StdRwLock::new(true), ..ApplicationInner::default() }),
126 default_handler: StdMutex::new(None),
127 phantom: PhantomData,
128 }
129 }
130
131 pub fn register_command_handler<F, Fut>(&self, handler: F) -> &Self
133 where
134 F: Fn(T, Arc<ApplicationInner>, Arc<ComponentFactoryManager>) -> (InitStrategy, Fut) + Send + Sync + 'static,
135 Fut: Future<Output = Result<()>> + Send + 'static,
136 {
137 let wrapped = move |cmd, inner, factories| {
139 let (strategy, fut) = handler(cmd, inner, factories);
140 (strategy, Box::pin(fut) as HandlerFuture)
141 };
142 let mut cmd_handler = self.command_handler.lock().expect("Failed to lock command_handler mutex");
143 *cmd_handler = Some(Box::new(wrapped) as CommandHandler<T>);
144 self
145 }
146
147 pub fn register_component_factory<Comp, F, Fut>(&self, label: Option<String>, factory: F) -> &Self
149 where
150 Comp: DynComponent + 'static,
151 F: Fn(Arc<ApplicationInner>, String) -> Fut + Send + Sync + 'static,
152 Fut: Future<Output = Result<Comp>> + Send + 'static,
153 {
154 self.component_factories.register_component_factory(label, factory);
155 self
156 }
157
158 pub fn set_default_handler<F, Fut>(&self, handler: F) -> &Self
160 where
161 F: Fn(Arc<ApplicationInner>, Arc<ComponentFactoryManager>) -> (InitStrategy, Fut) + Send + Sync + 'static,
162 Fut: Future<Output = Result<()>> + Send + 'static,
163 {
164 let wrapped = move |inner, factories| {
166 let (strategy, fut) = handler(inner, factories);
167 (strategy, Box::pin(fut) as HandlerFuture)
168 };
169 let mut def_handler = self.default_handler.lock().expect("Failed to lock default_handler mutex");
170 *def_handler = Some(Box::new(wrapped) as DefaultHandler);
171 self
172 }
173
174 pub fn set_wait_signal(&self, wait: bool) -> &Self {
176 self.inner.set_wait_signal(wait);
177 self
178 }
179
180 pub async fn get_all_component_keys(&self) -> Vec<ComponentKey> {
182 let components = self.inner.components.read().await;
183 components.keys().cloned().collect()
184 }
185
186 pub async fn run(&self) -> Result<()> {
188 let cli = Cli::<T>::parse();
189 self.load_config(&cli.config).await?;
190 let inner_arc = self.inner.clone();
191 let factories_arc = self.component_factories.clone();
192
193 let (init_strategy, execute_future) = match &cli.command {
195 Some(command) => {
196 let handler = self
197 .command_handler
198 .lock()
199 .map_err(|e| anyhow::anyhow!("get command handler lock failed: {}", e))?;
200 let handler = handler.as_ref().context("command handler not registered")?;
201 handler(command.clone(), inner_arc.clone(), factories_arc.clone())
202 }
203 None => {
204 let default_handler = self
205 .default_handler
206 .lock()
207 .map_err(|e| anyhow::anyhow!("get default handler lock failed: {}", e))?;
208 if cli.version {
209 self.set_wait_signal(false);
210 let fut: HandlerFuture = Box::pin(async {
211 if let Some(print_version) = GLOBAL_VERSION_PRINTER.get() {
212 print_version();
213 }
214 Ok(())
215 });
216 (InitStrategy::None, fut)
217 } else {
218 default_handler
219 .as_ref()
220 .map(|h| h(inner_arc.clone(), factories_arc.clone()))
221 .unwrap_or_else(|| {
222 let fut: HandlerFuture = Box::pin(async { Ok(()) });
223 (InitStrategy::All, fut)
224 })
225 }
226 }
227 };
228
229 self.init_components_with_strategy(init_strategy)
231 .await
232 .context("component init failed")?;
233
234 execute_future.await?;
236
237 let wait_signal = self
239 .inner
240 .wait_signal
241 .read()
242 .map_err(|e| anyhow::anyhow!("get wait signal lock failed: {}", e))?;
243 if *wait_signal {
244 info!("等待 ctrl+c 信号...");
245 shutdown_signal().await;
246 info!("收到 ctrl+c 信号,正在关闭应用...");
247 }
248
249 self.shutdown_components().await.context("shutdown component failed.")?;
251 println!("应用已退出");
252 sleep(Duration::from_millis(100)).await;
253 Ok(())
254 }
255
256 async fn init_components_with_strategy(&self, strategy: InitStrategy) -> Result<()> {
258 let inner = self.inner.clone();
259 let (factories, _) = self.component_factories.take_factories();
261
262 let filtered_factories: Vec<_> = match strategy {
264 InitStrategy::All => factories.iter().collect(),
265 InitStrategy::None => Vec::new(),
266 InitStrategy::Only(keys_to_init) => {
267 factories.iter().filter(|(key, _)| keys_to_init.contains(key)).collect()
268 }
269 InitStrategy::Deny(keys_to_deny) => {
270 factories.iter().filter(|(key, _)| !keys_to_deny.contains(key)).collect()
271 }
272 };
273
274 for (key, factory) in &filtered_factories {
276 let mut component = factory.create(inner.clone(), key.label.clone()).await?;
278 let type_name = component.type_name();
279
280 let config = inner.config.read().await;
282 component.init(&config, key.label.clone()).await?;
283 info!(com = type_name, label = &key.label, "组件创建并初始化成功");
284
285 let arc_component: Arc<dyn DynComponent> = Arc::from(component);
287 let mut components = inner.components.write().await;
289 components.insert(key.clone(), arc_component);
290 }
291
292 Ok(())
293 }
294
295 async fn shutdown_components(&self) -> Result<()> {
297 let inner = self.inner.clone();
298 let mut components = inner.components.write().await;
299 let mut component_keys: Vec<ComponentKey> = components.keys().cloned().collect();
300 component_keys.reverse(); for key in component_keys {
303 if let Some(component) = components.get(&key) {
304 let type_name = component.type_name();
305 component.shutdown().await?;
306 info!(com = type_name, label = &key.label, "组件关闭成功");
307 }
308 }
309
310 components.clear();
312 Ok(())
313 }
314
315 async fn load_config(&self, config_path: &Option<PathBuf>) -> Result<()> {
317 let mut config_builder = Config::builder();
318 if let Some(path) = config_path {
319 let path = fs::canonicalize(path).context(format!("canonicalize config path failed: {:?}", path))?;
320 config_builder = config_builder.add_source(File::from(path));
321 }
322 let config = config_builder.build().context("config load failed")?;
323 *self.inner.config.write().await = config;
324 Ok(())
325 }
326}
327
328impl<T: Subcommand + Clone + 'static> Default for App<T> {
329 fn default() -> Self {
330 Self::new()
331 }
332}
333
334impl App<EmptyCommand> {
335 pub fn with_empty_command() -> Self {
337 Self::new()
338 }
339}