use async_trait::async_trait;
#[async_trait]
pub trait DomainService: Send + Sync {
fn service_id(&self) -> &'static str;
async fn health_check(&self) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
Ok(())
}
fn service_name(&self) -> &'static str {
self.service_id()
.split('.')
.next_back()
.unwrap_or(self.service_id())
}
fn module_name(&self) -> &'static str {
self.service_id()
.split('.')
.next()
.unwrap_or("unknown")
}
}
#[async_trait]
pub trait TransactionalDomainService: DomainService {
async fn with_transaction<F, R, E>(&self, operation: F) -> Result<R, E>
where
F: FnOnce() -> Result<R, E> + Send,
R: Send,
E: Send;
}
#[cfg(test)]
mod tests {
use super::*;
struct TestService;
#[async_trait]
impl DomainService for TestService {
fn service_id(&self) -> &'static str {
"test.test_service"
}
}
#[test]
fn test_service_name_extraction() {
let service = TestService;
assert_eq!(service.service_name(), "test_service");
assert_eq!(service.module_name(), "test");
}
}