mirror of
https://github.com/searxng/searxng.git
synced 2025-08-02 18:12:21 +02:00
[enh] Add timeout limit per request (#1640)
The new url parameter "timeout_limit" set timeout limit defined in second. Example "timeout_limit=1.5" means the timeout limit is 1.5 seconds. In addition, the query can start with <[number] to set the timeout limit. For number between 0 and 99, the unit is the second : Example: "<30 searx" means the timeout limit is 3 seconds For number above 100, the unit is the millisecond: Example: "<850 searx" means the timeout is 850 milliseconds. In addition, there is a new optional setting: outgoing.max_request_timeout. If not set, the user timeout can't go above searx configuration (as before: the max timeout of selected engine for a query). If the value is set, the user can set a timeout between 0 and max_request_timeout using <[number] or timeout_limit query parameter. Related to #1077 Updated version of PR #1413 from @isj-privacore
This commit is contained in:
parent
2179079a91
commit
72029d27de
10 changed files with 180 additions and 15 deletions
|
@ -45,6 +45,16 @@ if sys.version_info[0] == 3:
|
|||
logger = logger.getChild('search')
|
||||
|
||||
number_of_searches = 0
|
||||
max_request_timeout = settings.get('outgoing', {}).get('max_request_timeout' or None)
|
||||
if max_request_timeout is None:
|
||||
logger.info('max_request_timeout={0}'.format(max_request_timeout))
|
||||
else:
|
||||
if isinstance(max_request_timeout, float):
|
||||
logger.info('max_request_timeout={0} second(s)'.format(max_request_timeout))
|
||||
else:
|
||||
logger.critical('outgoing.max_request_timeout if defined has to be float')
|
||||
from sys import exit
|
||||
exit(1)
|
||||
|
||||
|
||||
def send_http_request(engine, request_params):
|
||||
|
@ -265,6 +275,15 @@ def get_search_query_from_webapp(preferences, form):
|
|||
# query_engines
|
||||
query_engines = raw_text_query.engines
|
||||
|
||||
# timeout_limit
|
||||
query_timeout = raw_text_query.timeout_limit
|
||||
if query_timeout is None and 'timeout_limit' in form:
|
||||
raw_time_limit = form.get('timeout_limit')
|
||||
try:
|
||||
query_timeout = float(raw_time_limit)
|
||||
except ValueError:
|
||||
raise SearxParameterException('timeout_limit', raw_time_limit)
|
||||
|
||||
# query_categories
|
||||
query_categories = []
|
||||
|
||||
|
@ -338,7 +357,8 @@ def get_search_query_from_webapp(preferences, form):
|
|||
query_engines = deduplicate_query_engines(query_engines)
|
||||
|
||||
return (SearchQuery(query, query_engines, query_categories,
|
||||
query_lang, query_safesearch, query_pageno, query_time_range),
|
||||
query_lang, query_safesearch, query_pageno,
|
||||
query_time_range, query_timeout),
|
||||
raw_text_query)
|
||||
|
||||
|
||||
|
@ -351,6 +371,7 @@ class Search(object):
|
|||
super(Search, self).__init__()
|
||||
self.search_query = search_query
|
||||
self.result_container = ResultContainer()
|
||||
self.actual_timeout = None
|
||||
|
||||
# do search-request
|
||||
def search(self):
|
||||
|
@ -380,7 +401,7 @@ class Search(object):
|
|||
search_query = self.search_query
|
||||
|
||||
# max of all selected engine timeout
|
||||
timeout_limit = 0
|
||||
default_timeout = 0
|
||||
|
||||
# start search-reqest for all selected engines
|
||||
for selected_engine in search_query.engines:
|
||||
|
@ -420,12 +441,32 @@ class Search(object):
|
|||
# append request to list
|
||||
requests.append((selected_engine['name'], search_query.query, request_params))
|
||||
|
||||
# update timeout_limit
|
||||
timeout_limit = max(timeout_limit, engine.timeout)
|
||||
# update default_timeout
|
||||
default_timeout = max(default_timeout, engine.timeout)
|
||||
|
||||
# adjust timeout
|
||||
self.actual_timeout = default_timeout
|
||||
query_timeout = self.search_query.timeout_limit
|
||||
|
||||
if max_request_timeout is None and query_timeout is None:
|
||||
# No max, no user query: default_timeout
|
||||
pass
|
||||
elif max_request_timeout is None and query_timeout is not None:
|
||||
# No max, but user query: From user query except if above default
|
||||
self.actual_timeout = min(default_timeout, query_timeout)
|
||||
elif max_request_timeout is not None and query_timeout is None:
|
||||
# Max, no user query: Default except if above max
|
||||
self.actual_timeout = min(default_timeout, max_request_timeout)
|
||||
elif max_request_timeout is not None and query_timeout is not None:
|
||||
# Max & user query: From user query except if above max
|
||||
self.actual_timeout = min(query_timeout, max_request_timeout)
|
||||
|
||||
logger.debug("actual_timeout={0} (default_timeout={1}, ?timeout_limit={2}, max_request_timeout={3})"
|
||||
.format(self.actual_timeout, default_timeout, query_timeout, max_request_timeout))
|
||||
|
||||
# send all search-request
|
||||
if requests:
|
||||
# send all search-request
|
||||
search_multiple_requests(requests, self.result_container, start_time, timeout_limit)
|
||||
search_multiple_requests(requests, self.result_container, start_time, self.actual_timeout)
|
||||
start_new_thread(gc.collect, tuple())
|
||||
|
||||
# return results, suggestions, answers and infoboxes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue