alisaifee / limits

Rate limiting using various strategies and storage backends such as redis & memcached
https://limits.readthedocs.org
MIT License
428 stars 58 forks source link

How do you block until the rate has capacity? #221

Open iainelder opened 4 months ago

iainelder commented 4 months ago

Came here from Justin Van Winkle's survey of Python rate limiters. He said limits "seems to work", which is high praise because the rest were somehow broken.

Am I missing something with the hit function?

Quickstart shows how to assert whether it returns True or False and to sleep to make a previous False turn True.

assert True == moving_window.hit(one_per_minute, "test_namespace", "foo")
assert False == moving_window.hit(one_per_minute, "test_namespace", "foo")
assert True == moving_window.hit(one_per_minute, "test_namespace", "bar")

assert True == moving_window.hit(one_per_second, "test_namespace", "foo")
assert False == moving_window.hit(one_per_second, "test_namespace", "foo")
time.sleep(1)
assert True == moving_window.hit(one_per_second, "test_namespace", "foo")

I want a rate limiter that blocks until the request would satisfy the limit; that is, as soon as hit would return True.

I suppose I could built something like that using hit, but I don't want to. If I have to start writing sleeps into my code, then I think there's something missing from my rate limiter library.

iainelder commented 4 months ago

The Check without consuming example gave me a clue.

I need to add this pattern into any function that I want to be rate-limited.

while not moving_window.test(one_per_minute, "test_namespace"):
    time.sleep(0.01)
assert moving_window.hit(one_per_minute, "test_namespace")

Is that how you expect me to use this? If so, I would make a PR that clarifies this in the docs.

Better still would be a decorator (or indications on how to build one) so I don't have to add this inside my functions.