use crate::{AdaptiveService, Algorithm, ConcurrencyAlgorithm};
use std::sync::Arc;
use tower_layer::Layer;
pub struct AdaptiveLimiterLayer<A> {
algorithm: Arc<A>,
}
impl<A> AdaptiveLimiterLayer<A>
where
A: ConcurrencyAlgorithm,
{
pub fn new(algorithm: A) -> Self {
Self {
algorithm: Arc::new(algorithm),
}
}
pub fn builder() -> AdaptiveLimiterLayerBuilder {
AdaptiveLimiterLayerBuilder::new()
}
}
impl<A> Clone for AdaptiveLimiterLayer<A> {
fn clone(&self) -> Self {
Self {
algorithm: Arc::clone(&self.algorithm),
}
}
}
impl<S, A> Layer<S> for AdaptiveLimiterLayer<A>
where
A: ConcurrencyAlgorithm + 'static,
{
type Service = AdaptiveService<S, A>;
fn layer(&self, service: S) -> Self::Service {
AdaptiveService::new(service, Arc::clone(&self.algorithm))
}
}
pub struct AdaptiveLimiterLayerBuilder {
_private: (),
}
impl AdaptiveLimiterLayerBuilder {
fn new() -> Self {
Self { _private: () }
}
pub fn aimd(self) -> crate::AimdBuilder {
crate::Aimd::builder()
}
pub fn vegas(self) -> crate::VegasBuilder {
crate::Vegas::builder()
}
}
pub trait IntoLayer {
type Algorithm: ConcurrencyAlgorithm;
fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm>;
}
impl IntoLayer for crate::Aimd {
type Algorithm = crate::Aimd;
fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
AdaptiveLimiterLayer::new(self)
}
}
impl IntoLayer for crate::Vegas {
type Algorithm = crate::Vegas;
fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
AdaptiveLimiterLayer::new(self)
}
}
impl IntoLayer for Algorithm {
type Algorithm = Algorithm;
fn into_layer(self) -> AdaptiveLimiterLayer<Self::Algorithm> {
AdaptiveLimiterLayer::new(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Aimd;
use std::time::Duration;
#[test]
fn test_layer_creation() {
let algorithm = Aimd::builder()
.initial_limit(10)
.latency_threshold(Duration::from_millis(100))
.build();
let layer = AdaptiveLimiterLayer::new(algorithm);
let _ = layer.clone();
}
#[test]
fn test_into_layer() {
let layer = Aimd::builder().initial_limit(10).build().into_layer();
let _ = layer.clone();
}
}