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
			
		
		
			
		
	
	
					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
							 |