-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdjango_memcached_request_limit_manager.py
43 lines (35 loc) · 2.06 KB
/
django_memcached_request_limit_manager.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""pandadocument.py implements a Limit Manager for Django Application using Memcached
More about limits can be found here https://developers.pandadoc.com/reference#limits"""
__author__ = "Kostyantyn Ovechko"
__copyright__ = "Copyright 2020, Zxscript"
__license__ = "MIT"
__version__ = "0.0.1"
__email__ = "kos@zxscript.com"
__status__ = "Production"
import random
from time import sleep
from django.core.cache import cache
from .request_limit_manager import AbstractRequestLimitManager, RequestLimitReachedException
PANDADOC_REQUESTS_PER_MINUTE_QUOTA = 100
PANDADOC_REQUESTS_PER_MINUTE_DOWNLOAD_QUOTA = 20
class DjangoMemcachedRequestLimitManager(AbstractRequestLimitManager):
def get_request_permission(self):
# Set low priority for download - ONLY allow download within first 10 tokens
limit = PANDADOC_REQUESTS_PER_MINUTE_DOWNLOAD_QUOTA if self.for_download else PANDADOC_REQUESTS_PER_MINUTE_QUOTA
for attempt in range(0, self.max_attempts):
if attempt > 0:
print("Could NOT find a free token. Retrying after {retry_delay} seconds delay".format(
retry_delay=self.retry_delay))
sleep(self.retry_delay)
for idx in random.sample(range(0, limit), limit):
key = 'pandadoc_token_{idx}'.format(idx=idx)
# Beware we have some concurrency issue here - another process can acquire
# the same resource during .get_or_set() method call and if it's lucky enough to generate
# the same new_value. Hopefully, this won't happen too often. If unsure - consider
# setting lower PANDADOC_REQUESTS_PER_MINUTE_QUOTA than what you have provided by PandaDoc
new_value = random.randint(0, 99999999999999)
old_value = cache.get_or_set(key, new_value, 60)
if old_value == new_value:
print("Found free token at {key} value: {new_value}".format(key=key, new_value=new_value))
return True
raise RequestLimitReachedException('Please try again later.')