Skip to content

Instantly share code, notes, and snippets.

@bpeterso2000
Created August 2, 2019 10:08
Show Gist options
  • Save bpeterso2000/5e04046c6a1fc7397fa5e94a78af66f5 to your computer and use it in GitHub Desktop.
Save bpeterso2000/5e04046c6a1fc7397fa5e94a78af66f5 to your computer and use it in GitHub Desktop.
~/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