Compare commits

...

24 Commits

Author SHA1 Message Date
Mario de Frutos
3e6c273b48 Merge pull request #535 from CartoDB/development
Release 0.34.2
2018-11-27 18:04:11 +01:00
Mario de Frutos
522591dd63 Update NEWS.md 2018-11-27 17:51:45 +01:00
Mario de Frutos
75d0959aff Merge pull request #532 from CartoDB/fix_metrics
Fix metrics
2018-11-27 17:49:55 +01:00
Mario de Frutos
b2cdb378fb Regenerate 0.34.2 artifact 2018-11-27 17:43:02 +01:00
Mario de Frutos
100319ed0e Migrate old versions 2018-11-27 17:41:14 +01:00
Mario de Frutos
5e161b55d2 Merge branch 'development' into fix_metrics 2018-11-27 17:39:56 +01:00
Mario de Frutos
7f4b87f513 Rename to release 2018-11-27 17:39:05 +01:00
Mario de Frutos
378458c0ae Merge pull request #534 from CartoDB/development
Release 0.34.1 of the server extension
2018-11-22 15:15:13 +01:00
Mario de Frutos
4ae4080bba Updated NEWS.md 2018-11-22 15:10:11 +01:00
Mario de Frutos
2bb67ba17a Merge pull request #533 from CartoDB/fix_isochrones_metrics
Fix isochrones metrics
2018-11-22 15:07:57 +01:00
Mario de Frutos
1027d554a5 Upgrade script from 0.34.0 to 0.34.1 2018-11-19 18:23:28 +01:00
Mario de Frutos
4e1f081952 Generated 0.34.1 artifact with changes 2018-11-19 18:11:23 +01:00
Mario de Frutos
87bb8bea68 Remove duped metrics for isochrones
We are counting the success/empty inside the iteration of the results
returned by the third party service.

For example, if we ask for 3 isochrones to a provider we count:

- 1 for success or empty
- If success we add 1 more success for each isochrone in the result
- N isolines_generated

but it should be

- 1 for success or empty
- N isolines_generated
2018-11-19 17:59:47 +01:00
Mario de Frutos
dc47f6f71b New version 0.34.1 artifacts 2018-11-19 17:51:26 +01:00
Mario de Frutos
2f6d067b4e Parse JSON parameters to avoid problems
If we pass JSON as string, with scape characters and so on, we are
going to have problems parsing that metrics in ES
2018-11-05 17:06:52 +01:00
Mario de Frutos
089d3e3f27 New version 0.34.1 2018-11-05 16:51:17 +01:00
Mario de Frutos
765b2f0901 Merge pull request #529 from CartoDB/development
Release version 0.20.2 for python library
2018-10-31 14:00:31 +01:00
Mario de Frutos
36c42096e4 Updated NEWS.md 2018-10-31 13:58:29 +01:00
Mario de Frutos
909554b453 Merge pull request #528 from CartoDB/fix_qps_tomtom
Fix qps tomtom
2018-10-31 13:55:40 +01:00
Mario de Frutos
33f40bc945 TOMTOM uses 403 instead of 429 for rate limiting
That has a great problem when we're dealing with legit 403 status for
example deactivated user, forbidden access, etc.

I've added a check for the HTTP header `X-Error-Detail-Header` in order
to distinguish between legit 403 and 429 error messages

Possible values for `X-Error-Detail-Header` in a 403 error:

  o Service Requires SSL : http is used instead of https (secure)

  o Invalid Referer : invalid 'Referer' header value is send
  to https://api.tomtom.com and allowed referer values are
  configured on specific API key

  o Account Over Queries Per Second Limit : rate limit exceeded

  o Account Inactive : incorrect API key/API key no longer valid
2018-10-31 12:59:13 +01:00
Mario de Frutos
17c993f6ef Bump version 2018-10-24 12:00:44 +02:00
Mario de Frutos
6640909780 Add provider for QPS manger in tomtom services 2018-10-24 12:00:08 +02:00
Mario de Frutos
0e859d8955 Merge pull request #527 from CartoDB/change_isodistance_doc
Include note to explain why some isodistances could not be precise
2018-10-24 11:57:53 +02:00
Mario de Frutos
cd8173c7e0 Include note to explain why some isodistances could not be precise 2018-10-23 16:36:05 +02:00
18 changed files with 8073 additions and 12 deletions

22
NEWS.md
View File

@@ -1,3 +1,25 @@
Nov 27th, 2018
==============
* Version `0.34.2` of the server extension
* Fixed bulk geocoding log metrics in order to fix problems in ELK due to the JSON not being standard (#530)
Nov 22th, 2018
==============
* Version `0.34.1` of the server extension
* Fixed isochrones metrics that increase `success_rows` field for every isochrone generated (#533)
Oct 31th, 2018
==============
* Version `0.20.2` of the python library
* Added missing provider property to the QPS decorator in other TomTom services
* Now we only retry with the properly header coming from TomTom
Oct 3rd, 2018
==============
* Version `0.20.1` of the python library
* Fix QPS manager to retry with 403 status codes coming from TomTom
Sep 13th, 2018 Sep 13th, 2018
============== ==============
* Version `0.34.0` of the server, and `0.26.0` of the client. * Version `0.34.0` of the server, and `0.26.0` of the client.

View File

@@ -16,6 +16,8 @@ The following functions provide an isoline generator service, based on time or d
Displays a contoured line on a map, connecting geometries to a defined area, measured by an equal range of distance (in meters). Displays a contoured line on a map, connecting geometries to a defined area, measured by an equal range of distance (in meters).
Note that not all the providers, for example TomTom, provide us a way to define the isoline limit in distance so we need to make some estimations. Due that estimations the produced isolines could not be 100% precise.
#### Arguments #### Arguments
Name | Type | Description | Accepted values Name | Type | Description | Accepted values

View File

@@ -0,0 +1,39 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.34.1'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
import json
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_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
params = {'username': username, 'orgname': orgname, 'searches': json.loads(searches)}
with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params):
if user_geocoder_config.google_geocoder:
provider_function = "_cdb_bulk_google_geocode_street_point";
elif user_geocoder_config.heremaps_geocoder:
provider_function = "_cdb_bulk_heremaps_geocode_street_point";
elif user_geocoder_config.tomtom_geocoder:
provider_function = "_cdb_bulk_tomtom_geocode_street_point";
elif user_geocoder_config.mapbox_geocoder:
provider_function = "_cdb_bulk_mapbox_geocode_street_point";
else:
raise Exception('Requested geocoder is not available')
plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"])
return plpy.execute(plan, [username, orgname, searches])
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;

View File

@@ -0,0 +1,39 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.34.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_point(username TEXT, orgname TEXT, searches jsonb)
RETURNS SETOF cdb_dataservices_server.geocoding AS $$
from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger
import json
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_geocoder_config({0}, {1})".format(plpy.quote_nullable(username), plpy.quote_nullable(orgname)))
user_geocoder_config = GD["user_geocoder_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
params = {'username': username, 'orgname': orgname, 'searches': searches}
with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params):
if user_geocoder_config.google_geocoder:
provider_function = "_cdb_bulk_google_geocode_street_point";
elif user_geocoder_config.heremaps_geocoder:
provider_function = "_cdb_bulk_heremaps_geocode_street_point";
elif user_geocoder_config.tomtom_geocoder:
provider_function = "_cdb_bulk_tomtom_geocode_street_point";
elif user_geocoder_config.mapbox_geocoder:
provider_function = "_cdb_bulk_mapbox_geocode_street_point";
else:
raise Exception('Requested geocoder is not available')
plan = plpy.prepare("SELECT * FROM cdb_dataservices_server.{}($1, $2, $3); ".format(provider_function), ["text", "text", "jsonb"])
return plpy.execute(plan, [username, orgname, searches])
$$ LANGUAGE plpythonu STABLE PARALLEL RESTRICTED;

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
comment = 'CartoDB dataservices server extension' comment = 'CartoDB dataservices server extension'
default_version = '0.34.0' default_version = '0.34.2'
requires = 'plpythonu, plproxy, postgis, cdb_geocoder' requires = 'plpythonu, plproxy, postgis, cdb_geocoder'
superuser = true superuser = true
schema = cdb_dataservices_server schema = cdb_dataservices_server

View File

@@ -0,0 +1,182 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.34.1'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
from cartodb_services.mapzen.types import coordinates_to_polygon
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
# -- Check the quota
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
logger, user_isolines_routing_config.mapzen_isochrones_service_params)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
result.append([source, isochrone.duration, result_polygon])
else:
result.append([source, isochrone.duration, None])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(result))
return result
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isochrones')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.tools import ServiceManager
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
from cartodb_services.tools import Coordinate
from cartodb_services.tools.coordinates import coordinates_to_polygon
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
import cartodb_services
cartodb_services.init(plpy, GD)
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
service_manager.assert_within_limits()
try:
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = Coordinate(lon,lat)
else:
raise Exception('source is NULL')
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
result.append([source, isochrone.duration, result_polygon])
else:
result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result))
return result
else:
service_manager.quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
service_manager.quota_service.increment_failed_service_use()
service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get Mapbox isochrones')
finally:
service_manager.quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.tools import ServiceManager
from cartodb_services.tomtom import TomTomIsolines
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
from cartodb_services.tools import Coordinate
from cartodb_services.tools.coordinates import coordinates_to_polygon
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
import cartodb_services
cartodb_services.init(plpy, GD)
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
service_manager.assert_within_limits()
try:
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = Coordinate(lon,lat)
else:
raise Exception('source is NULL')
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
result.append([source, isochrone.duration, result_polygon])
else:
result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result))
return result
else:
service_manager.quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
service_manager.quota_service.increment_failed_service_use()
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get TomTom isochrones')
finally:
service_manager.quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;

View File

@@ -0,0 +1,188 @@
--DO NOT MODIFY THIS FILE, IT IS GENERATED AUTOMATICALLY FROM SOURCES
-- Complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "ALTER EXTENSION cdb_dataservices_server UPDATE TO '0.34.0'" to load this file. \quit
-- HERE goes your code to upgrade/downgrade
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapzen_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
import json
from cartodb_services.mapzen import MatrixClient, MapzenIsochrones
from cartodb_services.metrics import QuotaService
from cartodb_services.tools import Logger,LoggerConfig
from cartodb_services.mapzen.types import coordinates_to_polygon
redis_conn = GD["redis_connection_{0}".format(username)]['redis_metrics_connection']
user_isolines_routing_config = GD["user_isolines_routing_config_{0}".format(username)]
plpy.execute("SELECT cdb_dataservices_server._get_logger_config()")
logger_config = GD["logger_config"]
logger = Logger(logger_config)
# -- Check the quota
quota_service = QuotaService(user_isolines_routing_config, redis_conn)
if not quota_service.check_user_quota():
raise Exception('You have reached the limit of your quota')
try:
mapzen_isochrones = MapzenIsochrones(user_isolines_routing_config.mapzen_matrix_api_key,
logger, user_isolines_routing_config.mapzen_isochrones_service_params)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = {'lat': lat, 'lon': lon}
else:
raise Exception('source is NULL')
resp = mapzen_isochrones.isochrone(origin, mode, data_range)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon])
else:
quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None])
quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(result))
return result
else:
quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
quota_service.increment_failed_service_use()
logger.error('Error trying to get mapzen isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get mapzen isochrones')
finally:
quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_mapbox_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.tools import ServiceManager
from cartodb_services.mapbox import MapboxMatrixClient, MapboxIsolines
from cartodb_services.mapbox.types import TRANSPORT_MODE_TO_MAPBOX
from cartodb_services.tools import Coordinate
from cartodb_services.tools.coordinates import coordinates_to_polygon
from cartodb_services.refactor.service.mapbox_isolines_config import MapboxIsolinesConfigBuilder
import cartodb_services
cartodb_services.init(plpy, GD)
service_manager = ServiceManager('isolines', MapboxIsolinesConfigBuilder, username, orgname, GD)
service_manager.assert_within_limits()
try:
client = MapboxMatrixClient(service_manager.config.mapbox_api_key, service_manager.logger, service_manager.config.service_params)
mapbox_isolines = MapboxIsolines(client, service_manager.logger)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = Coordinate(lon,lat)
else:
raise Exception('source is NULL')
profile = TRANSPORT_MODE_TO_MAPBOX.get(mode)
resp = mapbox_isolines.calculate_isochrone(origin, data_range, profile)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
service_manager.quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon])
else:
service_manager.quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result))
return result
else:
service_manager.quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
service_manager.quota_service.increment_failed_service_use()
service_manager.logger.error('Error trying to get Mapbox isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get Mapbox isochrones')
finally:
service_manager.quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_tomtom_isochrones(
username TEXT,
orgname TEXT,
source geometry(Geometry, 4326),
mode TEXT,
data_range integer[],
options text[])
RETURNS SETOF cdb_dataservices_server.isoline AS $$
from cartodb_services.tools import ServiceManager
from cartodb_services.tomtom import TomTomIsolines
from cartodb_services.tomtom.types import TRANSPORT_MODE_TO_TOMTOM
from cartodb_services.tools import Coordinate
from cartodb_services.tools.coordinates import coordinates_to_polygon
from cartodb_services.refactor.service.tomtom_isolines_config import TomTomIsolinesConfigBuilder
import cartodb_services
cartodb_services.init(plpy, GD)
service_manager = ServiceManager('isolines', TomTomIsolinesConfigBuilder, username, orgname, GD)
service_manager.assert_within_limits()
try:
tomtom_isolines = TomTomIsolines(service_manager.config.tomtom_api_key, service_manager.logger, service_manager.config.service_params)
if source:
lat = plpy.execute("SELECT ST_Y('%s') AS lat" % source)[0]['lat']
lon = plpy.execute("SELECT ST_X('%s') AS lon" % source)[0]['lon']
origin = Coordinate(lon,lat)
else:
raise Exception('source is NULL')
profile = TRANSPORT_MODE_TO_TOMTOM.get(mode)
resp = tomtom_isolines.calculate_isochrone(origin, data_range, profile)
if resp:
result = []
for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon:
service_manager.quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon])
else:
service_manager.quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result))
return result
else:
service_manager.quota_service.increment_empty_service_use()
return []
except BaseException as e:
import sys
service_manager.quota_service.increment_failed_service_use()
service_manager.logger.error('Error trying to get TomTom isochrones', sys.exc_info(), data={"username": username, "orgname": orgname})
raise Exception('Error trying to get TomTom isochrones')
finally:
service_manager.quota_service.increment_total_service_use()
$$ LANGUAGE plpythonu SECURITY DEFINER STABLE PARALLEL RESTRICTED;

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@ CREATE OR REPLACE FUNCTION cdb_dataservices_server._cdb_bulk_geocode_street_poin
RETURNS SETOF cdb_dataservices_server.geocoding AS $$ RETURNS SETOF cdb_dataservices_server.geocoding AS $$
from cartodb_services.metrics import metrics from cartodb_services.metrics import metrics
from cartodb_services.tools import Logger from cartodb_services.tools import Logger
import json
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']
@@ -20,7 +21,7 @@ RETURNS SETOF cdb_dataservices_server.geocoding AS $$
logger_config = GD["logger_config"] logger_config = GD["logger_config"]
logger = Logger(logger_config) logger = Logger(logger_config)
params = {'username': username, 'orgname': orgname, 'searches': searches} params = {'username': username, 'orgname': orgname, 'searches': json.loads(searches)}
with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params): with metrics('cdb_bulk_geocode_street_point', user_geocoder_config, logger, params):
if user_geocoder_config.google_geocoder: if user_geocoder_config.google_geocoder:

View File

@@ -295,10 +295,8 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
for isochrone in resp: for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates) result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon: if result_polygon:
quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon]) result.append([source, isochrone.duration, result_polygon])
else: else:
quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None]) result.append([source, isochrone.duration, None])
quota_service.increment_success_service_use() quota_service.increment_success_service_use()
quota_service.increment_isolines_service_use(len(result)) quota_service.increment_isolines_service_use(len(result))
@@ -356,10 +354,8 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
for isochrone in resp: for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates) result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon: if result_polygon:
service_manager.quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon]) result.append([source, isochrone.duration, result_polygon])
else: else:
service_manager.quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None]) result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use() service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result)) service_manager.quota_service.increment_isolines_service_use(len(result))
@@ -416,10 +412,8 @@ RETURNS SETOF cdb_dataservices_server.isoline AS $$
for isochrone in resp: for isochrone in resp:
result_polygon = coordinates_to_polygon(isochrone.coordinates) result_polygon = coordinates_to_polygon(isochrone.coordinates)
if result_polygon: if result_polygon:
service_manager.quota_service.increment_success_service_use()
result.append([source, isochrone.duration, result_polygon]) result.append([source, isochrone.duration, result_polygon])
else: else:
service_manager.quota_service.increment_empty_service_use()
result.append([source, isochrone.duration, None]) result.append([source, isochrone.duration, None])
service_manager.quota_service.increment_success_service_use() service_manager.quota_service.increment_success_service_use()
service_manager.quota_service.increment_isolines_service_use(len(result)) service_manager.quota_service.increment_isolines_service_use(len(result))

View File

@@ -70,7 +70,7 @@ class TomTomGeocoder(Traceable):
return False return False
@qps_retry(qps=5) @qps_retry(qps=5, provider='tomtom')
def geocode(self, searchtext, city=None, state_province=None, def geocode(self, searchtext, city=None, state_province=None,
country=None): country=None):
response = self.geocode_meta(searchtext, city, state_province, country) response = self.geocode_meta(searchtext, city, state_province, country)
@@ -80,7 +80,7 @@ class TomTomGeocoder(Traceable):
else: else:
return response[0] return response[0]
@qps_retry(qps=5) @qps_retry(qps=5, provider='tomtom')
def geocode_meta(self, searchtext, city=None, state_province=None, def geocode_meta(self, searchtext, city=None, state_province=None,
country=None): country=None):
if searchtext: if searchtext:

View File

@@ -89,7 +89,7 @@ class TomTomRouting(Traceable):
point[ENTRY_LONGITUDE])) point[ENTRY_LONGITUDE]))
return geometry return geometry
@qps_retry(qps=5) @qps_retry(qps=5, provider='tomtom')
def directions(self, waypoints, profile=DEFAULT_PROFILE, def directions(self, waypoints, profile=DEFAULT_PROFILE,
date_time=DEFAULT_DEPARTAT): date_time=DEFAULT_DEPARTAT):
self._validate_profile(profile) self._validate_profile(profile)

View File

@@ -6,6 +6,9 @@ from exceptions import TimeoutException
DEFAULT_RETRY_TIMEOUT = 60 DEFAULT_RETRY_TIMEOUT = 60
DEFAULT_QUERIES_PER_SECOND = 10 DEFAULT_QUERIES_PER_SECOND = 10
TOMTOM_403_RATE_LIMIT_HEADER = 'Account Over Queries Per Second Limit'
TOMTOM_DETAIL_HEADER = 'X-Error-Detail-Header'
def qps_retry(original_function=None, **options): def qps_retry(original_function=None, **options):
""" Query Per Second retry decorator """ Query Per Second retry decorator
@@ -46,6 +49,8 @@ class QPSService:
response = getattr(e, 'response', None) response = getattr(e, 'response', None)
if response is not None: if response is not None:
if self._provider is not None and self._provider == 'tomtom' and (response.status_code == 403): if self._provider is not None and self._provider == 'tomtom' and (response.status_code == 403):
if response.headers.get(TOMTOM_DETAIL_HEADER) != TOMTOM_403_RATE_LIMIT_HEADER:
raise e
self.retry(start_time, attempt_number) self.retry(start_time, attempt_number)
elif response.status_code == 429: elif response.status_code == 429:
self.retry(start_time, attempt_number) self.retry(start_time, attempt_number)

View File

@@ -10,7 +10,7 @@ from setuptools import setup, find_packages
setup( setup(
name='cartodb_services', name='cartodb_services',
version='0.20.1', version='0.20.2',
description='CartoDB Services API Python Library', description='CartoDB Services API Python Library',