use std::sync::Arc;
use ff_core::engine_backend::EngineBackend;
#[cfg(any(
feature = "layer-tracing",
feature = "layer-ratelimit",
feature = "layer-metrics",
feature = "layer-circuit-breaker",
))]
mod hooks;
#[cfg(feature = "layer-circuit-breaker")]
mod circuit_breaker;
#[cfg(feature = "layer-metrics")]
mod metrics;
#[cfg(feature = "layer-ratelimit")]
mod ratelimit;
#[cfg(feature = "layer-tracing")]
mod tracing_layer;
#[cfg(feature = "layer-circuit-breaker")]
pub use circuit_breaker::{CircuitBreakerConfig, CircuitBreakerLayer};
#[cfg(feature = "layer-metrics")]
pub use metrics::{MetricsLayer, MetricsSink, NoopSink, Outcome};
#[cfg(feature = "layer-ratelimit")]
pub use ratelimit::{RateLimitKey, RateLimitKeyFn, RateLimitLayer};
#[cfg(feature = "layer-tracing")]
pub use tracing_layer::TracingLayer;
mod sealed {
pub trait SealedExt {}
impl<T: ?Sized> SealedExt for std::sync::Arc<T> where T: ff_core::engine_backend::EngineBackend {}
pub trait SealedLayer {}
}
pub trait EngineBackendLayer: sealed::SealedLayer + Send + Sync + 'static {
fn layer(&self, inner: Arc<dyn EngineBackend>) -> Arc<dyn EngineBackend>;
}
impl<F> sealed::SealedLayer for F where
F: Fn(Arc<dyn EngineBackend>) -> Arc<dyn EngineBackend> + Send + Sync + 'static
{
}
impl<F> EngineBackendLayer for F
where
F: Fn(Arc<dyn EngineBackend>) -> Arc<dyn EngineBackend> + Send + Sync + 'static,
{
fn layer(&self, inner: Arc<dyn EngineBackend>) -> Arc<dyn EngineBackend> {
(self)(inner)
}
}
pub trait EngineBackendLayerExt: sealed::SealedExt {
fn layer<L: EngineBackendLayer>(self, layer: L) -> Arc<dyn EngineBackend>;
}
impl EngineBackendLayerExt for Arc<dyn EngineBackend> {
fn layer<L: EngineBackendLayer>(self, layer: L) -> Arc<dyn EngineBackend> {
layer.layer(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::layer::test_support::PassthroughBackend;
use std::sync::atomic::{AtomicUsize, Ordering};
#[test]
fn closure_blanket_impl_wraps() {
let counter = Arc::new(AtomicUsize::new(0));
let counter_for_layer = counter.clone();
let layer = move |inner: Arc<dyn EngineBackend>| -> Arc<dyn EngineBackend> {
counter_for_layer.fetch_add(1, Ordering::SeqCst);
inner
};
let backend: Arc<dyn EngineBackend> = Arc::new(PassthroughBackend::default());
let _layered = backend.layer(layer);
assert_eq!(counter.load(Ordering::SeqCst), 1);
}
#[test]
fn zero_layer_case_arc_itself_is_a_backend() {
let backend: Arc<dyn EngineBackend> = Arc::new(PassthroughBackend::default());
let _ = backend;
}
}
#[cfg(any(
test,
all(test, feature = "layer-tracing"),
all(test, feature = "layer-ratelimit"),
all(test, feature = "layer-metrics"),
all(test, feature = "layer-circuit-breaker"),
))]
pub(crate) mod test_support;