use std::convert::Infallible;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
use tower::{Service, ServiceBuilder, ServiceExt};
use tower_acc::{ConcurrencyLimitLayer, Vegas};
const BUFFER_SIZE: usize = 8;
#[derive(Clone)]
struct Echo;
impl Service<String> for Echo {
type Response = String;
type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<String, Infallible>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: String) -> Self::Future {
Box::pin(async move {
tokio::time::sleep(Duration::from_millis(50)).await;
Ok(format!("echo: {req}"))
})
}
}
#[tokio::main]
async fn main() {
let algorithm = Vegas::builder().initial_limit(2).max_limit(10).build();
let svc = ServiceBuilder::new()
.load_shed()
.buffer(BUFFER_SIZE)
.layer(ConcurrencyLimitLayer::new(algorithm))
.service(Echo);
let mut handles = Vec::new();
for i in 0..20 {
let mut svc = svc.clone();
handles.push(tokio::spawn(async move {
match svc.ready().await {
Ok(svc) => match svc.call(format!("request {i}")).await {
Ok(resp) => println!(" ok: {resp}"),
Err(err) => println!("shed: request {i} ({err})"),
},
Err(err) => println!("shed: request {i} ({err})"),
}
}));
}
for handle in handles {
handle.await.unwrap();
}
}