Merge pull request #89 from CartoDB/routing_quota_check
Quota check for the routing feature
This commit is contained in:
commit
c4d682a5a5
@ -1,12 +1,12 @@
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_routing_config(username text, orgname text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_isolines_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_routing_config_{0}".format(username)
|
||||
cache_key = "user_isolines_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import RoutingConfig
|
||||
from cartodb_services.metrics import IsolinesRoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
heremaps_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('heremaps_conf') as heremaps_conf", 1)[0]['heremaps_conf']
|
||||
@ -17,7 +17,7 @@ RETURNS boolean AS $$
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
heremaps_app_id = heremaps_conf['app_id']
|
||||
heremaps_app_code = heremaps_conf['app_code']
|
||||
routing_config = RoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
routing_config = IsolinesRoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = routing_config
|
||||
@ -34,12 +34,15 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
# -- Check the quota
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
plpy.error('You have reach the limit of your quota')
|
||||
|
||||
try:
|
||||
client = HereMapsRoutingIsoline(user_routing_config.heremaps_app_id, user_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.PRODUCTION_ROUTING_BASE_URL)
|
||||
client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, user_isolines_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.PRODUCTION_ROUTING_BASE_URL)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
@ -80,8 +83,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isodistance'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
@ -99,8 +102,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT,
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isochrone'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
|
@ -1,5 +1,5 @@
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_isochrone(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server.cdb_isodistance(TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._cdb_here_routing_isolines(TEXT, TEXT, TEXT, geometry(Geometry, 4326), TEXT, integer[], text[]);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._get_routing_config(text, text);
|
||||
DROP FUNCTION IF EXISTS cdb_dataservices_server._get_isolines_routing_config(text, text);
|
||||
DROP TYPE IF EXISTS cdb_dataservices_server.isoline;
|
@ -85,14 +85,14 @@ RETURNS boolean AS $$
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_routing_config(username text, orgname text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_isolines_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_routing_config_{0}".format(username)
|
||||
cache_key = "user_isolines_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import RoutingConfig
|
||||
from cartodb_services.metrics import IsolinesRoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
heremaps_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('heremaps_conf') as heremaps_conf", 1)[0]['heremaps_conf']
|
||||
@ -103,10 +103,10 @@ RETURNS boolean AS $$
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
heremaps_app_id = heremaps_conf['app_id']
|
||||
heremaps_app_code = heremaps_conf['app_code']
|
||||
routing_config = RoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
isolines_routing_config = IsolinesRoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = routing_config
|
||||
GD[cache_key] = isolines_routing_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
-- Geocodes a street address given a searchtext and a state and/or country
|
||||
@ -814,12 +814,15 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
# -- Check the quota
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
plpy.error('You have reach the limit of your quota')
|
||||
|
||||
try:
|
||||
client = HereMapsRoutingIsoline(user_routing_config.heremaps_app_id, user_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.STAGING_ROUTING_BASE_URL )
|
||||
client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, user_isolines_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.PRODUCTION_ROUTING_BASE_URL)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
@ -859,8 +862,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isodistance'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
@ -877,8 +880,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT,
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isochrone'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
|
@ -25,14 +25,14 @@ RETURNS boolean AS $$
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
||||
-- Get the Redis configuration from the _conf table --
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_routing_config(username text, orgname text)
|
||||
CREATE OR REPLACE FUNCTION cdb_dataservices_server._get_isolines_routing_config(username text, orgname text)
|
||||
RETURNS boolean AS $$
|
||||
cache_key = "user_routing_config_{0}".format(username)
|
||||
cache_key = "user_isolines_routing_config_{0}".format(username)
|
||||
if cache_key in GD:
|
||||
return False
|
||||
else:
|
||||
import json
|
||||
from cartodb_services.metrics import RoutingConfig
|
||||
from cartodb_services.metrics import IsolinesRoutingConfig
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
||||
heremaps_conf_json = plpy.execute("SELECT cartodb.CDB_Conf_GetConf('heremaps_conf') as heremaps_conf", 1)[0]['heremaps_conf']
|
||||
@ -43,9 +43,9 @@ RETURNS boolean AS $$
|
||||
heremaps_conf = json.loads(heremaps_conf_json)
|
||||
heremaps_app_id = heremaps_conf['app_id']
|
||||
heremaps_app_code = heremaps_conf['app_code']
|
||||
routing_config = RoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
isolines_routing_config = IsolinesRoutingConfig(redis_conn, username, orgname, heremaps_app_id, heremaps_app_code)
|
||||
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||
# --for this user session but...
|
||||
GD[cache_key] = routing_config
|
||||
GD[cache_key] = isolines_routing_config
|
||||
return True
|
||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||
|
@ -8,12 +8,15 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
user_routing_config = GD["user_routing_config_{0}".format(username)]
|
||||
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
|
||||
quota_service = QuotaService(user_routing_config, redis_conn)
|
||||
# -- Check the quota
|
||||
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
|
||||
if not quota_service.check_user_quota():
|
||||
plpy.error('You have reach the limit of your quota')
|
||||
|
||||
try:
|
||||
client = HereMapsRoutingIsoline(user_routing_config.heremaps_app_id, user_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.PRODUCTION_ROUTING_BASE_URL)
|
||||
client = HereMapsRoutingIsoline(user_isolines_routing_config.heremaps_app_id, user_isolines_routing_config.heremaps_app_code, base_url = HereMapsRoutingIsoline.PRODUCTION_ROUTING_BASE_URL)
|
||||
|
||||
if source:
|
||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
||||
|
@ -2,8 +2,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isodistance(username TEXT
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isodistance'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
|
@ -2,8 +2,8 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server.cdb_isochrone(username TEXT,
|
||||
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_routing_config_{0}".format(username)]
|
||||
plpy.execute("SELECT cdb_dataservices_server._get_isolines_routing_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
|
||||
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||
type = 'isochrone'
|
||||
|
||||
here_plan = plpy.prepare("SELECT cdb_dataservices_server._cdb_here_routing_isolines($1, $2, $3, $4, $5, $6, $7) as isoline; ", ["text", "text", "text", "geometry(Geometry, 4326)", "text", "integer[]", "text[]"])
|
||||
|
@ -1,3 +1,3 @@
|
||||
from config import GeocoderConfig, RoutingConfig, InternalGeocoderConfig, ConfigException
|
||||
from config import GeocoderConfig, IsolinesRoutingConfig, InternalGeocoderConfig, ConfigException
|
||||
from quota import QuotaService
|
||||
from user import UserMetricsService
|
||||
|
@ -28,18 +28,76 @@ class ServiceConfig(object):
|
||||
return self._orgname
|
||||
|
||||
|
||||
class RoutingConfig(ServiceConfig):
|
||||
class IsolinesRoutingConfig(ServiceConfig):
|
||||
|
||||
ROUTING_CONFIG_KEYS = ['here_isolines_quota', 'soft_here_isolines_limit',
|
||||
'period_end_date', 'username', 'orgname',
|
||||
'heremaps_app_id', 'heremaps_app_code']
|
||||
NOKIA_APP_ID_KEY = 'heremaps_app_id'
|
||||
NOKIA_APP_CODE_KEY = 'heremaps_app_code'
|
||||
QUOTA_KEY = 'here_isolines_quota'
|
||||
SOFT_LIMIT_KEY = 'soft_here_isolines_limit'
|
||||
USERNAME_KEY = 'username'
|
||||
ORGNAME_KEY = 'orgname'
|
||||
PERIOD_END_DATE = 'period_end_date'
|
||||
|
||||
def __init__(self, redis_connection, username, orgname=None,
|
||||
heremaps_app_id=None, heremaps_app_code=None):
|
||||
super(RoutingConfig, self).__init__(redis_connection,
|
||||
username, orgname)
|
||||
self._heremaps_app_id = heremaps_app_id
|
||||
self._heremaps_app_code = heremaps_app_code
|
||||
super(IsolinesRoutingConfig, self).__init__(redis_connection, username,
|
||||
orgname)
|
||||
config = self.__get_user_config(username, orgname, heremaps_app_id,
|
||||
heremaps_app_code)
|
||||
filtered_config = {key: config[key] for key in self.ROUTING_CONFIG_KEYS if key in config.keys()}
|
||||
self.__parse_config(filtered_config)
|
||||
|
||||
def __get_user_config(self, username, orgname=None, heremaps_app_id=None,
|
||||
heremaps_app_code=None):
|
||||
user_config = self._redis_connection.hgetall(
|
||||
"rails:users:{0}".format(username))
|
||||
if not user_config:
|
||||
raise ConfigException("""There is no user config available. Please check your configuration.'""")
|
||||
else:
|
||||
user_config[self.NOKIA_APP_ID_KEY] = heremaps_app_id
|
||||
user_config[self.NOKIA_APP_CODE_KEY] = heremaps_app_code
|
||||
if orgname:
|
||||
self.__get_organization_config(orgname, user_config)
|
||||
|
||||
return user_config
|
||||
|
||||
def __get_organization_config(self, orgname, user_config):
|
||||
org_config = self._redis_connection.hgetall(
|
||||
"rails:orgs:{0}".format(orgname))
|
||||
if not org_config:
|
||||
raise ConfigException("""There is no organization config available. Please check your configuration.'""")
|
||||
else:
|
||||
user_config[self.QUOTA_KEY] = org_config[self.QUOTA_KEY]
|
||||
user_config[self.PERIOD_END_DATE] = org_config[self.PERIOD_END_DATE]
|
||||
|
||||
def __parse_config(self, filtered_config):
|
||||
self._isolines_quota = float(filtered_config[self.QUOTA_KEY])
|
||||
self._period_end_date = date_parse(filtered_config[self.PERIOD_END_DATE])
|
||||
if filtered_config[self.SOFT_LIMIT_KEY].lower() == 'true':
|
||||
self._soft_isolines_limit = True
|
||||
else:
|
||||
self._soft_isolines_limit = False
|
||||
self._heremaps_app_id = filtered_config[self.NOKIA_APP_ID_KEY]
|
||||
self._heremaps_app_code = filtered_config[self.NOKIA_APP_CODE_KEY]
|
||||
|
||||
@property
|
||||
def service_type(self):
|
||||
return 'routing_here'
|
||||
return 'here_isolines'
|
||||
|
||||
@property
|
||||
def isolines_quota(self):
|
||||
return self._isolines_quota
|
||||
|
||||
@property
|
||||
def soft_isolines_limit(self):
|
||||
return self._soft_isolines_limit
|
||||
|
||||
@property
|
||||
def period_end_date(self):
|
||||
return self._period_end_date
|
||||
|
||||
@property
|
||||
def heremaps_app_id(self):
|
||||
|
@ -1,32 +1,22 @@
|
||||
from user import UserMetricsService
|
||||
from datetime import date
|
||||
import re
|
||||
|
||||
|
||||
class QuotaService:
|
||||
""" Class to manage all the quota operation for
|
||||
the Geocoder SQL API Extension """
|
||||
|
||||
def __init__(self, user_geocoder_config, redis_connection):
|
||||
self._user_geocoder_config = user_geocoder_config
|
||||
def __init__(self, user_service_config, redis_connection):
|
||||
self._user_service_config = user_service_config
|
||||
# TODO First step to extract to a factory if needed in the future
|
||||
self._quota_checker = QuotaChecker(user_service_config,
|
||||
redis_connection)
|
||||
self._user_service = UserMetricsService(
|
||||
self._user_geocoder_config, redis_connection)
|
||||
self._user_service_config, redis_connection)
|
||||
|
||||
def check_user_quota(self):
|
||||
""" Check if the current user quota surpasses the current quota """
|
||||
# We don't have quota check for google geocoder
|
||||
if self._user_geocoder_config.google_geocoder:
|
||||
return True
|
||||
|
||||
user_quota = self._user_geocoder_config.geocoding_quota
|
||||
today = date.today()
|
||||
service_type = self._user_geocoder_config.service_type
|
||||
current_used = self._user_service.used_quota(service_type, today)
|
||||
soft_geocoding_limit = self._user_geocoder_config.soft_geocoding_limit
|
||||
|
||||
if soft_geocoding_limit or current_used <= user_quota:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return self._quota_checker.check()
|
||||
|
||||
# TODO
|
||||
# We are going to change this class to be the generic one and
|
||||
@ -36,25 +26,72 @@ class QuotaService:
|
||||
|
||||
def increment_success_geocoder_use(self, amount=1):
|
||||
self._user_service.increment_service_use(
|
||||
self._user_geocoder_config.service_type, "success_responses",
|
||||
self._user_service_config.service_type, "success_responses",
|
||||
amount=amount)
|
||||
|
||||
def increment_empty_geocoder_use(self, amount=1):
|
||||
self._user_service.increment_service_use(
|
||||
self._user_geocoder_config.service_type, "empty_responses",
|
||||
self._user_service_config.service_type, "empty_responses",
|
||||
amount=amount)
|
||||
|
||||
def increment_failed_geocoder_use(self, amount=1):
|
||||
self._user_service.increment_service_use(
|
||||
self._user_geocoder_config.service_type, "fail_responses",
|
||||
self._user_service_config.service_type, "fail_responses",
|
||||
amount=amount)
|
||||
|
||||
def increment_total_geocoder_use(self, amount=1):
|
||||
self._user_service.increment_service_use(
|
||||
self._user_geocoder_config.service_type, "total_requests",
|
||||
self._user_service_config.service_type, "total_requests",
|
||||
amount=amount)
|
||||
|
||||
def increment_isolines_service_use(self, amount=1):
|
||||
self._user_service.increment_service_use(
|
||||
self._user_geocoder_config.service_type, "isolines_generated",
|
||||
self._user_service_config.service_type, "isolines_generated",
|
||||
amount=amount)
|
||||
|
||||
|
||||
class QuotaChecker:
|
||||
|
||||
def __init__(self, user_service_config, redis_connection):
|
||||
self._user_service_config = user_service_config
|
||||
self._user_service = UserMetricsService(
|
||||
self._user_service_config, redis_connection)
|
||||
|
||||
def check(self):
|
||||
""" Check if the current user quota surpasses the current quota """
|
||||
if re.match('geocoder_*',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_geocoder_quota()
|
||||
elif re.match('here_isolines',
|
||||
self._user_service_config.service_type) is not None:
|
||||
return self.__check_isolines_quota()
|
||||
else:
|
||||
return False
|
||||
|
||||
def __check_geocoder_quota(self):
|
||||
# We don't have quota check for google geocoder
|
||||
if self._user_service_config.google_geocoder:
|
||||
return True
|
||||
|
||||
user_quota = self._user_service_config.geocoding_quota
|
||||
today = date.today()
|
||||
service_type = self._user_service_config.service_type
|
||||
current_used = self._user_service.used_quota(service_type, today)
|
||||
soft_geocoding_limit = self._user_service_config.soft_geocoding_limit
|
||||
|
||||
if soft_geocoding_limit or (user_quota > 0 and current_used <= user_quota):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __check_isolines_quota(self):
|
||||
user_quota = self._user_service_config.isolines_quota
|
||||
today = date.today()
|
||||
service_type = self._user_service_config.service_type
|
||||
current_used = self._user_service.used_quota(service_type, today)
|
||||
soft_isolines_limit = self._user_service_config.soft_isolines_limit
|
||||
|
||||
if soft_isolines_limit or (user_quota > 0 and current_used <= user_quota):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -6,16 +6,8 @@ class UserMetricsService:
|
||||
""" Class to manage all the user info """
|
||||
|
||||
SERVICE_GEOCODER_NOKIA = 'geocoder_here'
|
||||
SERVICE_GEOCODER_GOOGLE = 'geocoder_google'
|
||||
SERVICE_GEOCODER_CACHE = 'geocoder_cache'
|
||||
|
||||
GEOCODING_QUOTA_KEY = "geocoding_quota"
|
||||
GEOCODING_SOFT_LIMIT_KEY = "soft_geocoder_limit"
|
||||
|
||||
REDIS_CONNECTION_KEY = "redis_connection"
|
||||
REDIS_CONNECTION_HOST = "redis_host"
|
||||
REDIS_CONNECTION_PORT = "redis_port"
|
||||
REDIS_CONNECTION_DB = "redis_db"
|
||||
SERVICE_HERE_ISOLINES = 'here_isolines'
|
||||
|
||||
def __init__(self, user_geocoder_config, redis_connection):
|
||||
self._user_geocoder_config = user_geocoder_config
|
||||
@ -24,6 +16,12 @@ class UserMetricsService:
|
||||
self._orgname = user_geocoder_config.organization
|
||||
|
||||
def used_quota(self, service_type, date):
|
||||
if service_type == self.SERVICE_HERE_ISOLINES:
|
||||
return self.__used_isolines_quota(service_type, date)
|
||||
else:
|
||||
return self.__used_geocoding_quota(service_type, date)
|
||||
|
||||
def __used_geocoding_quota(self, service_type, date):
|
||||
""" Recover the used quota for the user in the current month """
|
||||
date_from, date_to = self.__current_billing_cycle()
|
||||
current_use = 0
|
||||
@ -42,6 +40,20 @@ class UserMetricsService:
|
||||
|
||||
return current_use
|
||||
|
||||
def __used_isolines_quota(self, service_type, date):
|
||||
date_from, date_to = self.__current_billing_cycle()
|
||||
current_use = 0
|
||||
isolines_generated = self.get_metrics(service_type,
|
||||
'isolines_generated', date_from,
|
||||
date_to)
|
||||
empty_responses = self.get_metrics(service_type,
|
||||
'empty_responses', date_from,
|
||||
date_to)
|
||||
current_use += (isolines_generated + empty_responses)
|
||||
|
||||
return current_use
|
||||
|
||||
|
||||
def increment_service_use(self, service_type, metric, date=date.today(), amount=1):
|
||||
""" Increment the services uses in monthly and daily basis"""
|
||||
self.__increment_user_uses(service_type, metric, date, amount)
|
||||
|
Loading…
Reference in New Issue
Block a user