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

Possible regression from 0.4 to 0.5 #157

Closed
AaronErhardt opened this issue Nov 21, 2022 · 6 comments · Fixed by #159
Closed

Possible regression from 0.4 to 0.5 #157

AaronErhardt opened this issue Nov 21, 2022 · 6 comments · Fixed by #159

Comments

@AaronErhardt
Copy link
Contributor

Maintainer of actix-governor here.

After upgrading actix-governor's version of governor, our test cases started to tail.
It doesn't look like the rate-limiting itself is broken, but the reporting of the remaining burst size.

While looking through the changes I noticed that this test was added:

https://github.com/antifuchs/governor/blob/b8d99cf6b01c1969bce2e3497986b2ae59d33ac4/governor/tests/middleware.rs#L73-L102

According to the test, everything seemed to work as expected: After one check, the remaining burst size goes down by one.
Yet in our tests it went down from two to zero in just one step.

After some testing I found that using FakeRelativeClock made a difference.
Running with the fake clock works, but with a real clock it doesn't anymore.

This test case shows this behavior:

#[test]
fn state_snapshot_tracks_quota_accurately() {
    use governor::middleware::StateInformationMiddleware;
    use governor::{Quota, RateLimiter};
    use std::num::NonZeroU32;
    use std::time::Duration;

    let burst_size = NonZeroU32::new(2).unwrap();
    let period = Duration::from_millis(90);
    let quota = Quota::with_period(period).unwrap().allow_burst(burst_size);

    let clock = FakeRelativeClock::default();

    // First test
    let lim = RateLimiter::direct_with_clock(quota, &clock)
        .with_middleware::<StateInformationMiddleware>();

    assert_eq!(lim.check().unwrap().remaining_burst_capacity(), 1);
    assert_eq!(lim.check().unwrap().remaining_burst_capacity(), 0);
    assert_eq!(lim.check().map_err(|_| ()), Err(()), "should rate limit");

    // Now with a real clock
    let lim = RateLimiter::direct(quota)
        .with_middleware::<StateInformationMiddleware>();

    assert_eq!(lim.check().unwrap().remaining_burst_capacity(), 1); // <- This returns 0 instead
    assert_eq!(lim.check().unwrap().remaining_burst_capacity(), 0);
    assert_eq!(lim.check().map_err(|_| ()), Err(()), "should rate limit");
}
@antifuchs
Copy link
Collaborator

Hrmmmmm! Thanks for the report. This is pretty concerning - I hoped that this time, I'd have gotten the clock behavior right so tests reflect actual reality. I'll dig, but can't promise that I'll get it done before the holidays. /:

@antifuchs
Copy link
Collaborator

Actually, this seems to be easier than I thought: The tests involving futures&"real" clocks end up failing when the quota reporting is fixed, and exhibit very weird & flakey behavior. I suspect that quanta (the clock provider) is being a bit odd (it used to inject "calibration" runs the first time you'd measure, which added 50 or so millis of jitter to every test run).

@antifuchs
Copy link
Collaborator

Think I've got a fix for this, in #159! Hope tests pass this time around (:

bors bot added a commit that referenced this issue Nov 29, 2022
159: Correctly report quota in StateInformationMiddleware r=antifuchs a=antifuchs

This fix was previously prevented from passing tests by flakey quanta clock tests. I believe by lengthening the intervals and reducing the quota (thereby increasing the "time value" of each element), we can de-flake these tests somewhat, which lets this fix correctly pass.

Now, the problem was that the correct quota was reported only if a fake clock was used (i.e. if it remains at the zero nanosecond) - instead, we correctly compute the remaining capacity in all cases now.

This also extends the "remaining capacity" test by a few cases including a real clock.

Fixes #157 

Co-authored-by: Andreas Fuchs <asf@boinkor.net>
@bors bors bot closed this as completed in 77c4d45 Nov 29, 2022
@antifuchs
Copy link
Collaborator

Released in 0.5.1, which should hit docs.rs and crates.io in moments!

@AaronErhardt
Copy link
Contributor Author

Awesome! Actix-governor no longer lags behind the official governor release: AaronErhardt/actix-governor#37

Thanks a lot for this quick fix, Andreas!

@antifuchs
Copy link
Collaborator

Thank you for the super detailed & effective report!

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

Successfully merging a pull request may close this issue.

2 participants