84 lines
2.0 KiB
Python
84 lines
2.0 KiB
Python
import random
|
|
import sqlite3
|
|
import string
|
|
from pathlib import Path
|
|
from tempfile import gettempdir
|
|
from typing import List
|
|
|
|
from .abstracts import Rate
|
|
from .abstracts import RateItem
|
|
|
|
|
|
def binary_search(items: List[RateItem], value: int) -> int:
|
|
"""Find the index of item in list where left.timestamp < value <= right.timestamp
|
|
this is to determine the current size of some window that
|
|
stretches from now back to lower-boundary = value and
|
|
"""
|
|
if not items:
|
|
return 0
|
|
|
|
if value > items[-1].timestamp:
|
|
return -1
|
|
|
|
if value <= items[0].timestamp:
|
|
return 0
|
|
|
|
if len(items) == 2:
|
|
return 1
|
|
|
|
left_pointer, right_pointer, mid = 0, len(items) - 1, -2
|
|
|
|
while left_pointer <= right_pointer:
|
|
mid = (left_pointer + right_pointer) // 2
|
|
left, right = items[mid - 1].timestamp, items[mid].timestamp
|
|
|
|
if left < value <= right:
|
|
break
|
|
|
|
if left >= value:
|
|
right_pointer = mid
|
|
|
|
if right < value:
|
|
left_pointer = mid + 1
|
|
|
|
return mid
|
|
|
|
|
|
def validate_rate_list(rates: List[Rate]) -> bool:
|
|
"""Raise false if rates are incorrectly ordered."""
|
|
if not rates:
|
|
return False
|
|
|
|
for idx, current_rate in enumerate(rates[1:]):
|
|
prev_rate = rates[idx]
|
|
|
|
if current_rate.interval <= prev_rate.interval:
|
|
return False
|
|
|
|
if current_rate.limit <= prev_rate.limit:
|
|
return False
|
|
|
|
if (current_rate.limit / current_rate.interval) > (prev_rate.limit / prev_rate.interval):
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def id_generator(
|
|
size=6,
|
|
chars=string.ascii_uppercase + string.digits + string.ascii_lowercase,
|
|
) -> str:
|
|
return "".join(random.choice(chars) for _ in range(size))
|
|
|
|
|
|
def dedicated_sqlite_clock_connection():
|
|
temp_dir = Path(gettempdir())
|
|
default_db_path = temp_dir / "pyrate_limiter_clock_only.sqlite"
|
|
|
|
conn = sqlite3.connect(
|
|
default_db_path,
|
|
isolation_level="EXCLUSIVE",
|
|
check_same_thread=False,
|
|
)
|
|
return conn
|