vutran1710 / PyrateLimiter

⚔️Python Rate-Limiter using Leaky-Bucket Algorithm Family
https://pyratelimiter.readthedocs.io
MIT License
342 stars 36 forks source link

"Re-acquiring with delay expected to be successful" error for two rates for one bucket #184

Open PiotrB-123 opened 5 days ago

PiotrB-123 commented 5 days ago

Hi, first of all I'd like to thanks for this great work you put in this project. I have one problem, and maybe I'm using it wrong way. When I define two rates secodly and minutely for bucket it may lead to geting an error:

Re-acquiring with delay expected to be successful,
if it failed then either clock or bucket is probably unstable

Shortest possible testcase you can use to reproduce it:

import time
from pyrate_limiter import Duration, Rate, Limiter, InMemoryBucket, validate_rate_list

secondly_rate = Rate(1, Duration.SECOND * 7)  # 1/7s
minutely_rate = Rate(5, Duration.MINUTE)      # 5/60s

rates = [secondly_rate, minutely_rate]
assert validate_rate_list(rates)

basic_bucket = InMemoryBucket(rates)
limiter = Limiter(basic_bucket, raise_when_fail=False, max_delay=30 * Duration.SECOND)

start = time.time()

for x in range(10):
    print(f"\tAttempt: {x} Success: {limiter.try_acquire(f'item_{x}')} at T {time.time() - start:.2f}s")

and results I get is:

    Attempt: 0 Success: True at T 0.00s
    Attempt: 1 Success: True at T 7.05s
    Attempt: 2 Success: True at T 14.10s
    Attempt: 3 Success: True at T 21.15s
    Attempt: 4 Success: True at T 28.20s

                Re-acquiring with delay expected to be successful,
                if it failed then either clock or bucket is probably unstable

    Attempt: 5 Success: False at T 35.25s
    Attempt: 6 Success: True at T 60.05s
    Attempt: 7 Success: True at T 67.10s
    Attempt: 8 Success: True at T 74.15s
    Attempt: 9 Success: True at T 81.20s

I think rates a defined correctly and to be sure I used validate_rate_list. As I understand when bucket is full for secondly_rate it delays next put operation 7s, but then it fails on bucket full exceptoin for the second rate (minutely_rate), and Attempt 5 is lost.

Is there something I did wrong, or this is an issue in library code?

vutran1710 commented 5 days ago

Tks for filing the issue. Ill look at it soon.