Created
August 2, 2019 10:08
-
-
Save bpeterso2000/5e04046c6a1fc7397fa5e94a78af66f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
~/w/rest-client-boilerplate *… restclient cat ratelimiter.py | |
""" | |
Key-based Rate limiter | |
====================== | |
Rate limiter for API keys & resource ID's. | |
Not thread-safe; use something like redis for that. | |
""" | |
import threading | |
from datetime import datetime | |
from time import sleep | |
lock = threading.Lock() | |
# records datetime stamps for each request | |
log = {} | |
def _add_request(k, log, now): | |
with lock: | |
log[k].append(now) | |
lock.release() | |
def _prune_requests(k, log, num_seconds, now): | |
"""Drops request timestamps beyond the rate limit""" | |
log[k].sort() | |
with lock: | |
while now - log[k][-1] > num_seconds: | |
log[k].pop() | |
return log | |
def limit_rate(key, log, num_requests, now=datetime.now(), padding=.01): | |
k = hash(key) | |
if k not in log: | |
log[k] = [] | |
log = _prune_requests(k, log, now) | |
while len(log[k]) > num_requests: | |
wait = now - log[k][num-requests - 1] + padding | |
if len(log[k]) >= num_requests: | |
wait = now - log[k][num_requests - 1] | |
sleep(wait.seconds) | |
log = _add_request(k, log, now) | |
return log, wait |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment