]> git.openstreetmap.org Git - nominatim.git/commitdiff
add additional timeout for entire request
authorSarah Hoffmann <lonvia@denofr.de>
Fri, 25 Aug 2023 07:16:53 +0000 (09:16 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Fri, 25 Aug 2023 07:16:53 +0000 (09:16 +0200)
nominatim/api/core.py
nominatim/api/search/geocoder.py
settings/env.defaults

index c796244eca6a24389a83ea8d4645262f2cb06ab1..0f1dd7153af8f582410f398ab984d57ff8a18fb2 100644 (file)
@@ -194,7 +194,9 @@ class NominatimAPIAsync:
 
         async with self.begin() as conn:
             conn.set_query_timeout(self.query_timeout)
 
         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)
 
             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
 
                 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)
 
 
             return await geocoder.lookup(phrases)
 
 
@@ -276,7 +280,9 @@ class NominatimAPIAsync:
                 if details.keywords:
                     await make_query_analyzer(conn)
 
                 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)
 
 
             return await geocoder.lookup_pois(categories, phrases)
 
 
index 564e3d8dadc1df4181c5f3a2a5c4bfb86ade0c77..f88bffbd367bb3b78042375565dc22e820816e6f 100644 (file)
@@ -9,6 +9,7 @@ Public interface to the search code.
 """
 from typing import List, Any, Optional, Iterator, Tuple
 import itertools
 """
 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
 
 from nominatim.api.connection import SearchConnection
 from nominatim.api.types import SearchDetails
@@ -24,9 +25,11 @@ class ForwardGeocoder:
     """ Main class responsible for place search.
     """
 
     """ 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.conn = conn
         self.params = params
+        self.timeout = dt.timedelta(seconds=timeout or 1000000)
         self.query_analyzer: Optional[AbstractQueryAnalyzer] = None
 
 
         self.query_analyzer: Optional[AbstractQueryAnalyzer] = None
 
 
@@ -71,6 +74,7 @@ class ForwardGeocoder:
         """
         log().section('Execute database searches')
         results = SearchResults()
         """
         log().section('Execute database searches')
         results = SearchResults()
+        end_time = dt.datetime.now() + self.timeout
 
         num_results = 0
         min_ranking = 1000.0
 
         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
             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)
 
         if results:
             min_ranking = min(r.ranking for r in results)
index 7fe09fa4dc8ceb54c29e77c636249624bdbec693..ff0a7648741021377ce3009ad3eb48882ccb9940 100644 (file)
@@ -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.
 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.
 # 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
 
 # Search elements just within countries
 # If, despite not finding a point within the static grid of countries, it