6 changed files with 116 additions and 23 deletions
@ -0,0 +1,64 @@ |
|||||
|
import time |
||||
|
import gevent |
||||
|
|
||||
|
|
||||
|
class RouteState(object): |
||||
|
def __init__(self, route, request): |
||||
|
self.route = route |
||||
|
self.remaining = 0 |
||||
|
self.reset_time = 0 |
||||
|
self.event = None |
||||
|
|
||||
|
self.update(request) |
||||
|
|
||||
|
@property |
||||
|
def chilled(self): |
||||
|
return self.event is not None |
||||
|
|
||||
|
def update(self, request): |
||||
|
if 'X-RateLimit-Remaining' not in request.headers: |
||||
|
return |
||||
|
|
||||
|
self.remaining = int(request.headers.get('X-RateLimit-Remaining')) |
||||
|
self.reset_time = int(request.headers.get('X-RateLimit-Reset')) |
||||
|
|
||||
|
def wait(self, timeout=None): |
||||
|
self.event.wait(timeout) |
||||
|
|
||||
|
def next_will_ratelimit(self): |
||||
|
if self.remaining - 1 < 0 and time.time() <= self.reset_time: |
||||
|
return True |
||||
|
|
||||
|
return False |
||||
|
|
||||
|
def cooldown(self): |
||||
|
if self.reset_time - time.time() < 0: |
||||
|
raise Exception('Cannot cooldown for negative time period; check clock sync') |
||||
|
|
||||
|
self.event = gevent.event.Event() |
||||
|
gevent.sleep((self.reset_time - time.time()) + .5) |
||||
|
self.event.set() |
||||
|
self.event = None |
||||
|
|
||||
|
|
||||
|
class RateLimiter(object): |
||||
|
def __init__(self): |
||||
|
self.cooldowns = {} |
||||
|
self.states = {} |
||||
|
|
||||
|
def check(self, route, timeout=None): |
||||
|
if route in self.states: |
||||
|
# If we're current waiting, join the club |
||||
|
if self.states[route].chilled: |
||||
|
return self.states[route].wait(timeout) |
||||
|
|
||||
|
if self.states[route].next_will_ratelimit(): |
||||
|
self.states[route].cooldown() |
||||
|
|
||||
|
return True |
||||
|
|
||||
|
def update(self, route, request): |
||||
|
if route in self.states: |
||||
|
self.states[route].update(request) |
||||
|
else: |
||||
|
self.states[route] = RouteState(route, request) |
Loading…
Reference in new issue