You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.3 KiB

3 years ago
import time
from deprecated.sphinx import deprecated
from limits.storage.memcached import MemcachedStorage
@deprecated(
reason="""The implementation has not been tested at all
in version 2.0 (and for many years) and will be removed in limits 2.5""",
version="2.0",
action="once",
)
class GAEMemcachedStorage(MemcachedStorage): # noqa
"""
rate limit storage with GAE memcache as backend
"""
MAX_CAS_RETRIES = 10
STORAGE_SCHEME = ["gaememcached"]
def __init__(self, uri: str, **options):
options["library"] = "google.appengine.api.memcache"
super().__init__(uri, **options)
def incr(
self, key: str, expiry: int, elastic_expiry: bool = False, amount: int = 1
):
"""
increments the counter for a given rate limit key
:param key: the key to increment
:param expiry: amount in seconds for the key to expire in
:param elastic_expiry: whether to keep extending the rate limit
window every hit.
:param amount: the number to increment by
"""
if not self.call_memcached_func(self.storage.add, key, amount, expiry):
if elastic_expiry:
# CAS id is set as state on the client object in GAE memcache
value = self.storage.gets(key)
retry = 0
while (
not self.call_memcached_func(
self.storage.cas, key, int(value or 0) + amount, expiry
)
and retry < self.MAX_CAS_RETRIES
):
value = self.storage.gets(key)
retry += 1
self.call_memcached_func(
self.storage.set, key + "/expires", expiry + time.time(), expiry
)
return int(value or 0) + amount
else:
return self.storage.incr(key, amount)
self.call_memcached_func(
self.storage.set, key + "/expires", expiry + time.time(), expiry
)
return 1
def check(self) -> bool:
"""
check if storage is healthy
"""
try:
self.call_memcached_func(self.storage.get_stats)
return True
except: # noqa
return False