Complete rate-limiting for Mapzen & Here gecoding
ServiceManager class has been introduced to handle service configuration at SQL level (with a LegacyServiceManager alternative for non-refactored services). These new classes take the responsibility of rate limits and quota checking. Tests have been added for ServiceManager and rate limits, but currently they check only the limits configuration since Lua support would be needed to use rratelimit with MockRedis.
This commit is contained in:
@@ -50,14 +50,15 @@ class RateLimitsConfigBuilder(object):
|
||||
def get(self):
|
||||
# Order of precedence is user_conf, org_conf, server_conf
|
||||
|
||||
rate_limit_key = "{0}_rate_limit".format(service)
|
||||
rate_limit_key = "{0}_rate_limit".format(self._service)
|
||||
rate_limit_json = self._user_conf.get(rate_limit_key, None) or self._org_conf.get(rate_limit_key, None)
|
||||
if (rate_limit_json):
|
||||
rate_limit = rate_limit_json and json.loads(rate_limit_json)
|
||||
else:
|
||||
rate_limit = self._server_conf.get('rate_limits', {}).get(service, {})
|
||||
rate_limit = self._server_conf.get('rate_limits', {}).get(self._service, {})
|
||||
|
||||
return RateLimitsConfig(self._service,
|
||||
self._username,
|
||||
self._limit,
|
||||
self._period)
|
||||
rate_limit.get('limit', None),
|
||||
rate_limit.get('period', None))
|
||||
|
||||
|
||||
@@ -6,6 +6,6 @@ class ConfigBackendInterface(object):
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, key):
|
||||
def get(self, key, default=None):
|
||||
"""Return a value based on the key supplied from some storage"""
|
||||
pass
|
||||
|
||||
@@ -5,8 +5,8 @@ class InMemoryConfigStorage(ConfigBackendInterface):
|
||||
def __init__(self, config_hash={}):
|
||||
self._config_hash = config_hash
|
||||
|
||||
def get(self, key):
|
||||
def get(self, key, default=None):
|
||||
try:
|
||||
return self._config_hash[key]
|
||||
except KeyError:
|
||||
return None
|
||||
return default
|
||||
|
||||
@@ -2,5 +2,5 @@ from ..core.interfaces import ConfigBackendInterface
|
||||
|
||||
class NullConfigStorage(ConfigBackendInterface):
|
||||
|
||||
def get(self, key):
|
||||
return None
|
||||
def get(self, key, default=None):
|
||||
return default
|
||||
|
||||
+5
-3
@@ -9,11 +9,13 @@ class RedisConfigStorage(ConfigBackendInterface):
|
||||
self._config_key = config_key
|
||||
self._data = None
|
||||
|
||||
def get(self, key):
|
||||
def get(self, key, default=KeyError):
|
||||
if not self._data:
|
||||
self._data = self._connection.hgetall(self._config_key)
|
||||
return self._data[key]
|
||||
|
||||
if (default == KeyError):
|
||||
return self._data[key]
|
||||
else:
|
||||
return self._data.get(key, default)
|
||||
|
||||
class RedisUserConfigStorageBuilder(object):
|
||||
def __init__(self, redis_connection, username):
|
||||
|
||||
+11
-4
@@ -4,11 +4,18 @@ from ..core.interfaces import ConfigBackendInterface
|
||||
|
||||
class InDbServerConfigStorage(ConfigBackendInterface):
|
||||
|
||||
def get(self, key):
|
||||
def get(self, key, default=None):
|
||||
sql = "SELECT cdb_dataservices_server.cdb_conf_getconf('{0}') as conf".format(key)
|
||||
rows = cartodb_services.plpy.execute(sql, 1)
|
||||
json_output = rows[0]['conf']
|
||||
if json_output:
|
||||
json_output = None
|
||||
try:
|
||||
json_output = rows[0]['conf']
|
||||
except IndexError:
|
||||
pass
|
||||
if (json_output):
|
||||
return json.loads(json_output)
|
||||
else:
|
||||
return None
|
||||
if (default == KeyError):
|
||||
raise KeyError
|
||||
else:
|
||||
return default
|
||||
|
||||
Reference in New Issue
Block a user