Closed JWCook closed 3 years ago
If I were you in this case, I would either
Meanwhile, I really don't want to touch the constructor. So if you can go with one of the two points above in a PR, I think we can have such feature.
Fair enough. Maybe this doesn't need changes in pyrate-limiter, then, and I can just add a subclass in my own project(s).
Just curious, what is the intended use case for multiple buckets on the same Limiter? Would that be for tracking separate limits for requests to multiple hosts? Or for some use case other than HTTP requests?
Fair enough. Maybe this doesn't need changes in pyrate-limiter, then, and I can just add a subclass in my own project(s).
Just curious, what is the intended use case for multiple buckets on the same Limiter? Would that be for tracking separate limits for requests to multiple hosts? Or for some use case other than HTTP requests?
Yes. Back in the day I started developing this, I was working on a microservice architecture, where a single backend app might send multiple requests to different apps.
Okay, that makes sense. I asked because I was considering making an extension to integrate this with the requests
library, probably as a separate package. It would work as a transport adapter that would run requests within a Limiter.ratelimit
contextmanager. That would potentially allow setting different rate limits for different hosts.
Usage might look something like:
from requests import Session
from requests_pyrate_limiter import LimiterAdapter # or some other package name
from pyrate_limiter import Duration, RequestRate
adapter = LimiterAdapter(RequestRate(10, Duration.SECOND))
session = Session()
# Apply rate-limiting to all requests (maybe using a separate bucket per host?)
session.mount('http://', adapter)
session.mount('https://', adapter)
# Apply a different rate limit to a specific host
adapter_2 = LimiterAdapter(RequestRate(2, Duration.SECOND))
session.mount('https://api.some_site.com', adapter_2)
# Make rate-limited requests that stay within 2 requests per second
for user_id in range(100):
response = session.get(f'https://api.some_site.com/v1/users/{user_id}')
Personally I would find something like that convenient because all my settings would then be contained in one session
object, along with other things like retry behavior, cookies, hooks, etc.
What do you think?
Okay, that makes sense. I asked because I was considering making an extension to integrate this with the
requests
library, probably as a separate package. It would work as a transport adapter that would run requests within aLimiter.ratelimit
contextmanager. That would potentially allow setting different rate limits for different hosts.Usage might look something like:
from requests import Session from requests_pyrate_limiter import LimiterAdapter # or some other package name from pyrate_limiter import Duration, RequestRate adapter = LimiterAdapter(RequestRate(10, Duration.SECOND)) session = Session() # Apply rate-limiting to all requests (maybe using a separate bucket per host?) session.mount('http://', adapter) session.mount('https://', adapter) # Apply a different rate limit to a specific host adapter_2 = LimiterAdapter(RequestRate(2, Duration.SECOND)) session.mount('https://api.some_site.com', adapter_2) # Make rate-limited requests that stay within 2 requests per second for user_id in range(100): response = session.get(f'https://api.some_site.com/v1/users/{user_id}')
Personally I would find something like that convenient because all my settings would then be contained in one
session
object, along with other things like retry behavior, cookies, hooks, etc.What do you think?
That looks nice. Definitely something I would use on my daily work
Cool, I'll ping you when I have something ready to test out.
@vutran1710 Fyi, I have a work-in-progress repo for this here: https://github.com/JWCook/requests-ratelimiter
My current use case only requires one bucket/identity, which I imagine is fairly common. It would be convenient to be able to set a default identity on a
Limiter
object, which would be used if you don't specify one intry_acquire()
orratelimit()
.This would be especially useful if you're using the limiter in multiple locations. For example, instead of this:
I'd like to do this:
I think this would just require updating
Limiter._init_buckets()
. If that sounds good to you, I can make a PR for this.