feat: Add support for flexible throttling intervals

This commit introduces the ability to set custom time intervals for throttling,
allowing users to specify intervals like per 5 minutes, per 2 hours, and per 5 days.
This enhancement provides more flexibility in controlling request rates.
This commit is contained in:
Pravin Kamble 2023-08-20 23:21:03 +05:30
parent 40eccb0d6c
commit 68dbb4890c
2 changed files with 29 additions and 3 deletions

View File

@ -5,6 +5,7 @@ import time
from django.core.cache import cache as default_cache
from django.core.exceptions import ImproperlyConfigured
from utils.throttling_duration_parser import parse_quantity_and_unit
from rest_framework.settings import api_settings
@ -94,7 +95,7 @@ class SimpleRateThrottle(BaseThrottle):
msg = "No default throttle rate set for '%s' scope" % self.scope
raise ImproperlyConfigured(msg)
def parse_rate(self, rate):
def parse_rate(self,rate):
"""
Given the request rate string, return a two tuple of:
<allowed number of requests>, <period of time in seconds>
@ -102,9 +103,12 @@ class SimpleRateThrottle(BaseThrottle):
if rate is None:
return (None, None)
num, period = rate.split('/')
quantity, unit = parse_quantity_and_unit(period).values()
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[unit[0]]
total_duration = duration * int(quantity)
return (num_requests, total_duration)
def allow_request(self, request, view):
"""

View File

@ -0,0 +1,22 @@
def parse_quantity_and_unit(quantity_unit_string):
"""
Parse a combined quantity and unit string and return a dictionary containing the parsed values.
Args:
quantity_unit_string (str): A string that combines a numeric quantity and a unit, e.g., "5min", "10h".
Returns:
dict: A dictionary containing the parsed quantity and unit, with keys 'quantity' and 'unit'.
If the input string contains only a unit (e.g., "ms"), quantity will be set to 1.
"""
i = 0
quantity_unit_dict = {}
while i < len(quantity_unit_string) and quantity_unit_string[i].isnumeric():
i += 1
if i == 0:
quantity_unit_dict['quantity'] = 1
quantity_unit_dict['unit'] = quantity_unit_string
else:
quantity_unit_dict['quantity'] = int(quantity_unit_string[:i])
quantity_unit_dict['unit'] = quantity_unit_string[i:]
return quantity_unit_dict