From: Sarah Hoffmann Date: Fri, 25 Aug 2023 07:16:53 +0000 (+0200) Subject: add additional timeout for entire request X-Git-Tag: v4.3.0~15^2 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/1115705cbcf6b3a6ae0f78ed09aa07bf4c1a72ca?ds=sidebyside add additional timeout for entire request --- diff --git a/nominatim/api/core.py b/nominatim/api/core.py index c796244e..0f1dd715 100644 --- a/nominatim/api/core.py +++ b/nominatim/api/core.py @@ -194,7 +194,9 @@ class NominatimAPIAsync: async with self.begin() as conn: conn.set_query_timeout(self.query_timeout) - geocoder = ForwardGeocoder(conn, ntyp.SearchDetails.from_kwargs(params)) + geocoder = ForwardGeocoder(conn, ntyp.SearchDetails.from_kwargs(params), + self.config.get_int('REQUEST_TIMEOUT') \ + if self.config.REQUEST_TIMEOUT else None) phrases = [Phrase(PhraseType.NONE, p.strip()) for p in query.split(',')] return await geocoder.lookup(phrases) @@ -252,7 +254,9 @@ class NominatimAPIAsync: if amenity: details.layers |= ntyp.DataLayer.POI - geocoder = ForwardGeocoder(conn, details) + geocoder = ForwardGeocoder(conn, details, + self.config.get_int('REQUEST_TIMEOUT') \ + if self.config.REQUEST_TIMEOUT else None) return await geocoder.lookup(phrases) @@ -276,7 +280,9 @@ class NominatimAPIAsync: if details.keywords: await make_query_analyzer(conn) - geocoder = ForwardGeocoder(conn, details) + geocoder = ForwardGeocoder(conn, details, + self.config.get_int('REQUEST_TIMEOUT') \ + if self.config.REQUEST_TIMEOUT else None) return await geocoder.lookup_pois(categories, phrases) diff --git a/nominatim/api/search/geocoder.py b/nominatim/api/search/geocoder.py index 564e3d8d..f88bffbd 100644 --- a/nominatim/api/search/geocoder.py +++ b/nominatim/api/search/geocoder.py @@ -9,6 +9,7 @@ Public interface to the search code. """ from typing import List, Any, Optional, Iterator, Tuple import itertools +import datetime as dt from nominatim.api.connection import SearchConnection from nominatim.api.types import SearchDetails @@ -24,9 +25,11 @@ class ForwardGeocoder: """ Main class responsible for place search. """ - def __init__(self, conn: SearchConnection, params: SearchDetails) -> None: + def __init__(self, conn: SearchConnection, + params: SearchDetails, timeout: Optional[int]) -> None: self.conn = conn self.params = params + self.timeout = dt.timedelta(seconds=timeout or 1000000) self.query_analyzer: Optional[AbstractQueryAnalyzer] = None @@ -71,6 +74,7 @@ class ForwardGeocoder: """ log().section('Execute database searches') results = SearchResults() + end_time = dt.datetime.now() + self.timeout num_results = 0 min_ranking = 1000.0 @@ -85,6 +89,8 @@ class ForwardGeocoder: log().result_dump('Results', ((r.accuracy, r) for r in results[num_results:])) num_results = len(results) prev_penalty = search.penalty + if dt.datetime.now() >= end_time: + break if results: min_ranking = min(r.ranking for r in results) diff --git a/settings/env.defaults b/settings/env.defaults index 7fe09fa4..ff0a7648 100644 --- a/settings/env.defaults +++ b/settings/env.defaults @@ -215,8 +215,14 @@ NOMINATIM_SERVE_LEGACY_URLS=yes NOMINATIM_API_POOL_SIZE=10 # Timeout is seconds after which a single query to the database is cancelled. +# The user receives a 503 response, when a query times out. # When empty, then timeouts are disabled. -NOMINATIM_QUERY_TIMEOUT=60 +NOMINATIM_QUERY_TIMEOUT=10 + +# Maximum time a single request is allowed to take. When the timeout is +# exceeeded, the available results are returned. +# When empty, then timouts are disabled. +NOMINATIM_REQUEST_TIMEOUT=60 # Search elements just within countries # If, despite not finding a point within the static grid of countries, it