1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
use crate::error::LightSpeedError; use log::info; #[async_trait::async_trait] pub trait ModuleBuilder<T: Module> { async fn build(&self) -> Result<T, LightSpeedError>; } #[async_trait::async_trait] pub trait Module { async fn start(&mut self) -> Result<(), LightSpeedError>; } pub async fn start(modules: &mut [&mut dyn Module]) -> Result<(), LightSpeedError> { info!("Begin modules 'start' phase"); for module in modules.iter_mut() { module.start().await?; } Ok(()) } #[cfg(test)] mod test { use crate::LightSpeedError; use std::sync::Arc; use tokio::sync::Mutex; #[tokio::test] async fn should_start_all() { let output = Arc::new(Mutex::new(vec![])); let mut mod1 = SimpleModOne { output: output.clone(), name: "one".to_string(), }; let mut mod2 = SimpleModTwo { output: output.clone(), name: "two".to_string(), fail: false, }; let mut modules: Vec<&mut dyn super::Module> = vec![&mut mod1, &mut mod2]; let result = super::start(modules.as_mut()).await; assert!(result.is_ok()); assert_eq!(2, output.lock().await.len()); assert_eq!( &"one-start".to_string(), output.lock().await.get(0).unwrap() ); assert_eq!( &"two-start".to_string(), output.lock().await.get(1).unwrap() ); } #[tokio::test] async fn should_fail_on_start() { let output = Arc::new(Mutex::new(vec![])); let mut mod1 = SimpleModOne { output: output.clone(), name: "one".to_string(), }; let mut mod2 = SimpleModTwo { output: output.clone(), name: "two".to_string(), fail: true, }; let mut modules: Vec<&mut dyn super::Module> = vec![&mut mod1, &mut mod2]; let result = super::start(&mut modules).await; assert!(result.is_err()); match result { Err(err) => match err { LightSpeedError::ModuleStartError { message } => { assert_eq!("test_failure", message) } _ => assert!(false), }, _ => assert!(false), } assert_eq!(1, output.lock().await.len()); assert_eq!( &"one-start".to_string(), output.lock().await.get(0).unwrap() ); } #[derive(Clone)] struct SimpleModOne { output: Arc<Mutex<Vec<String>>>, name: String, } #[async_trait::async_trait] impl super::Module for SimpleModOne { async fn start(&mut self) -> Result<(), LightSpeedError> { let mut owned = self.name.to_owned(); owned.push_str(&"-start"); self.output.lock().await.push(owned); Ok(()) } } #[derive(Clone)] struct SimpleModTwo { output: Arc<Mutex<Vec<String>>>, name: String, fail: bool, } #[async_trait::async_trait] impl super::Module for SimpleModTwo { async fn start(&mut self) -> Result<(), LightSpeedError> { if self.fail { return Err(LightSpeedError::ModuleStartError { message: "test_failure".to_owned(), }); } let mut owned = self.name.to_owned(); owned.push_str(&"-start"); self.output.lock().await.push(owned); Ok(()) } } }