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
use anthill_di::types::{BuildDependencyResult, BuildDependencyError};
use anthill_di::{Constructor, DependencyContext, DependencyLifeCycle};
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio::task::JoinHandle;
use super::IBaseService;
#[async_trait_with_sync::async_trait(Sync)]
pub trait IBackgroundService where Self: Send + Sync + 'static {
async fn execute(&self);
}
enum BackgroundServiceState {
Pending,
Started{ work_task: JoinHandle<()> },
}
pub struct BackgroundService<TService> where TService: IBackgroundService + Constructor {
pub service: Arc<RwLock<TService>>,
state: BackgroundServiceState,
}
#[async_trait_with_sync::async_trait(Sync)]
impl<TService> Constructor for BackgroundService<TService> where TService: IBackgroundService + Constructor {
async fn ctor(ctx: DependencyContext) -> BuildDependencyResult<Self> {
ctx.register_type::<RwLock<TService>>(DependencyLifeCycle::Singleton).await
.map_err(|e| BuildDependencyError::AddDependencyError{err: e})?
.map_as::<RwLock<dyn IBackgroundService>>().await.map_err(|e| BuildDependencyError::Custom { message: format!("{e:?}").to_string() })?;
Ok(Self {
service: ctx.resolve().await?,
state: BackgroundServiceState::Pending,
})
}
}
#[async_trait_with_sync::async_trait(Sync)]
impl<TService> IBaseService for BackgroundService<TService> where TService: IBackgroundService + Constructor {
async fn on_start(&mut self) {
let service_ref = self.service.clone();
self.state = BackgroundServiceState::Started{work_task: tokio::spawn(async move {
service_ref.read().await.execute().await;
})};
}
async fn on_stop(&mut self) {
if let BackgroundServiceState::Started{ work_task} = &mut self.state {
work_task.await.unwrap();
}
}
}