Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected behaviour of RateLimit #756

Open
hlbarber opened this issue Dec 6, 2023 · 0 comments
Open

unexpected behaviour of RateLimit #756

hlbarber opened this issue Dec 6, 2023 · 0 comments

Comments

@hlbarber
Copy link

hlbarber commented Dec 6, 2023

The following code

use std::time::{Duration, Instant};

use tower::{limit::rate::*, util::*};

#[tokio::main]
async fn main() {
    async fn foo(duration: Duration) -> Result<Instant, ()> {
        tokio::time::sleep(duration).await;
        Ok(Instant::now())
    }

    let svc = service_fn(foo);
    let rate = Rate::new(1, Duration::from_secs(1));
    let ref mut svc = RateLimit::new(svc, rate);

    let x = svc.oneshot(Duration::from_secs_f64(1.1)).await.unwrap();
    let y = svc.oneshot(Duration::from_secs_f32(0.1)).await.unwrap();
    println!("{}", (y - x).as_secs_f32());
}

prints ~0.1 because the rate limit is calculated over calls to the service rather than inflight requests. This is in contrast to ConcurrencyLimit whose Service::Future holds a semaphore permit until the request is complete.

I'd argue this behavior is unexpected - imagine tokio::time::sleep here represents some network jitter and the Rate variables correspond to a rate limit enforced by some server, under the current design using RateLimit<Client> can cause the server to receive twice the allowed requests in an interval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant