#![cfg_attr(coverage_nightly, coverage(off))]
use super::service_base::{Service, ServiceMetrics};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct ServiceAdapter<T, I, O> {
inner: Arc<T>,
metrics: Arc<RwLock<ServiceMetrics>>,
_phantom: PhantomData<(I, O)>,
}
impl<T, I, O> ServiceAdapter<T, I, O> {
pub fn new(inner: T) -> Self {
Self {
inner: Arc::new(inner),
metrics: Arc::new(RwLock::new(ServiceMetrics::default())),
_phantom: PhantomData,
}
}
#[must_use]
pub fn inner(&self) -> &T {
&self.inner
}
}
#[macro_export]
macro_rules! impl_service_adapter {
($adapter:ty, $input:ty, $output:ty, $process_fn:expr) => {
#[async_trait::async_trait]
impl Service for $adapter {
type Input = $input;
type Output = $output;
type Error = anyhow::Error;
async fn process(&self, input: Self::Input) -> Result<Self::Output, Self::Error> {
let start = std::time::Instant::now();
let result = $process_fn(&self.inner, input).await;
let duration = start.elapsed();
let mut metrics = self.metrics.write().await;
metrics.record_request(duration, result.is_ok());
result
}
fn metrics(&self) -> ServiceMetrics {
self.metrics.blocking_read().clone()
}
}
};
}
include!("service_adapter_complexity.rs");
include!("service_adapter_refactor.rs");
include!("service_adapter_registry.rs");
include!("service_adapter_tests.rs");