Merge pull request #89 from CartoDB/routing_quota_check
Quota check for the routing feature
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
-- Get the Redis configuration from the _conf table --
|
-- 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 $$
|
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:
|
if cache_key in GD:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
import json
|
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))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
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']
|
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_conf = json.loads(heremaps_conf_json)
|
||||||
heremaps_app_id = heremaps_conf['app_id']
|
heremaps_app_id = heremaps_conf['app_id']
|
||||||
heremaps_app_code = heremaps_conf['app_code']
|
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
|
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||||
# --for this user session but...
|
# --for this user session but...
|
||||||
GD[cache_key] = routing_config
|
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
|
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||||
|
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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:
|
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:
|
if source:
|
||||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isodistance'
|
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[]"])
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isochrone'
|
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[]"])
|
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_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_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._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;
|
DROP TYPE IF EXISTS cdb_dataservices_server.isoline;
|
||||||
@@ -85,14 +85,14 @@ RETURNS boolean AS $$
|
|||||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||||
|
|
||||||
-- Get the Redis configuration from the _conf table --
|
-- 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 $$
|
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:
|
if cache_key in GD:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
import json
|
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))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
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']
|
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_conf = json.loads(heremaps_conf_json)
|
||||||
heremaps_app_id = heremaps_conf['app_id']
|
heremaps_app_id = heremaps_conf['app_id']
|
||||||
heremaps_app_code = heremaps_conf['app_code']
|
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
|
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||||
# --for this user session but...
|
# --for this user session but...
|
||||||
GD[cache_key] = routing_config
|
GD[cache_key] = isolines_routing_config
|
||||||
return True
|
return True
|
||||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||||
-- Geocodes a street address given a searchtext and a state and/or country
|
-- 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
|
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||||
|
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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:
|
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:
|
if source:
|
||||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isodistance'
|
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[]"])
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isochrone'
|
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[]"])
|
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;
|
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
||||||
|
|
||||||
-- Get the Redis configuration from the _conf table --
|
-- 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 $$
|
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:
|
if cache_key in GD:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
import json
|
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))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metadata_connection']
|
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']
|
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_conf = json.loads(heremaps_conf_json)
|
||||||
heremaps_app_id = heremaps_conf['app_id']
|
heremaps_app_id = heremaps_conf['app_id']
|
||||||
heremaps_app_code = heremaps_conf['app_code']
|
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
|
# --Think about the security concerns with this kind of global cache, it should be only available
|
||||||
# --for this user session but...
|
# --for this user session but...
|
||||||
GD[cache_key] = routing_config
|
GD[cache_key] = isolines_routing_config
|
||||||
return True
|
return True
|
||||||
$$ LANGUAGE plpythonu SECURITY DEFINER;
|
$$ 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
|
from cartodb_services.here.types import geo_polyline_to_multipolygon
|
||||||
|
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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:
|
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:
|
if source:
|
||||||
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isodistance'
|
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[]"])
|
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 $$
|
RETURNS SETOF cdb_dataservices_server.isoline AS $$
|
||||||
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
plpy.execute("SELECT cdb_dataservices_server._connect_to_redis('{0}')".format(username))
|
||||||
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
|
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)))
|
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_routing_config_{0}".format(username)]
|
user_isolines_config = GD["user_isolines_routing_config_{0}".format(username)]
|
||||||
type = 'isochrone'
|
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[]"])
|
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 quota import QuotaService
|
||||||
from user import UserMetricsService
|
from user import UserMetricsService
|
||||||
|
|||||||
@@ -28,18 +28,76 @@ class ServiceConfig(object):
|
|||||||
return self._orgname
|
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,
|
def __init__(self, redis_connection, username, orgname=None,
|
||||||
heremaps_app_id=None, heremaps_app_code=None):
|
heremaps_app_id=None, heremaps_app_code=None):
|
||||||
super(RoutingConfig, self).__init__(redis_connection,
|
super(IsolinesRoutingConfig, self).__init__(redis_connection, username,
|
||||||
username, orgname)
|
orgname)
|
||||||
self._heremaps_app_id = heremaps_app_id
|
config = self.__get_user_config(username, orgname, heremaps_app_id,
|
||||||
self._heremaps_app_code = heremaps_app_code
|
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
|
@property
|
||||||
def service_type(self):
|
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
|
@property
|
||||||
def heremaps_app_id(self):
|
def heremaps_app_id(self):
|
||||||
|
|||||||
@@ -1,32 +1,22 @@
|
|||||||
from user import UserMetricsService
|
from user import UserMetricsService
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
class QuotaService:
|
class QuotaService:
|
||||||
""" Class to manage all the quota operation for
|
""" Class to manage all the quota operation for
|
||||||
the Geocoder SQL API Extension """
|
the Geocoder SQL API Extension """
|
||||||
|
|
||||||
def __init__(self, user_geocoder_config, redis_connection):
|
def __init__(self, user_service_config, redis_connection):
|
||||||
self._user_geocoder_config = user_geocoder_config
|
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_service = UserMetricsService(
|
||||||
self._user_geocoder_config, redis_connection)
|
self._user_service_config, redis_connection)
|
||||||
|
|
||||||
def check_user_quota(self):
|
def check_user_quota(self):
|
||||||
""" Check if the current user quota surpasses the current quota """
|
return self._quota_checker.check()
|
||||||
# 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
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# We are going to change this class to be the generic one and
|
# 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):
|
def increment_success_geocoder_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_geocoder_config.service_type, "success_responses",
|
self._user_service_config.service_type, "success_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
|
||||||
def increment_empty_geocoder_use(self, amount=1):
|
def increment_empty_geocoder_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_geocoder_config.service_type, "empty_responses",
|
self._user_service_config.service_type, "empty_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
|
||||||
def increment_failed_geocoder_use(self, amount=1):
|
def increment_failed_geocoder_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_geocoder_config.service_type, "fail_responses",
|
self._user_service_config.service_type, "fail_responses",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
|
||||||
def increment_total_geocoder_use(self, amount=1):
|
def increment_total_geocoder_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_geocoder_config.service_type, "total_requests",
|
self._user_service_config.service_type, "total_requests",
|
||||||
amount=amount)
|
amount=amount)
|
||||||
|
|
||||||
def increment_isolines_service_use(self, amount=1):
|
def increment_isolines_service_use(self, amount=1):
|
||||||
self._user_service.increment_service_use(
|
self._user_service.increment_service_use(
|
||||||
self._user_geocoder_config.service_type, "isolines_generated",
|
self._user_service_config.service_type, "isolines_generated",
|
||||||
amount=amount)
|
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 """
|
""" Class to manage all the user info """
|
||||||
|
|
||||||
SERVICE_GEOCODER_NOKIA = 'geocoder_here'
|
SERVICE_GEOCODER_NOKIA = 'geocoder_here'
|
||||||
SERVICE_GEOCODER_GOOGLE = 'geocoder_google'
|
|
||||||
SERVICE_GEOCODER_CACHE = 'geocoder_cache'
|
SERVICE_GEOCODER_CACHE = 'geocoder_cache'
|
||||||
|
SERVICE_HERE_ISOLINES = 'here_isolines'
|
||||||
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"
|
|
||||||
|
|
||||||
def __init__(self, user_geocoder_config, redis_connection):
|
def __init__(self, user_geocoder_config, redis_connection):
|
||||||
self._user_geocoder_config = user_geocoder_config
|
self._user_geocoder_config = user_geocoder_config
|
||||||
@@ -24,6 +16,12 @@ class UserMetricsService:
|
|||||||
self._orgname = user_geocoder_config.organization
|
self._orgname = user_geocoder_config.organization
|
||||||
|
|
||||||
def used_quota(self, service_type, date):
|
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 """
|
""" Recover the used quota for the user in the current month """
|
||||||
date_from, date_to = self.__current_billing_cycle()
|
date_from, date_to = self.__current_billing_cycle()
|
||||||
current_use = 0
|
current_use = 0
|
||||||
@@ -42,6 +40,20 @@ class UserMetricsService:
|
|||||||
|
|
||||||
return current_use
|
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):
|
def increment_service_use(self, service_type, metric, date=date.today(), amount=1):
|
||||||
""" Increment the services uses in monthly and daily basis"""
|
""" Increment the services uses in monthly and daily basis"""
|
||||||
self.__increment_user_uses(service_type, metric, date, amount)
|
self.__increment_user_uses(service_type, metric, date, amount)
|
||||||
|
|||||||
Reference in New Issue
Block a user