From d9296e85b944003e1c1974f89f17e9530854a41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Honza=20Kr=C3=A1l?= Date: Mon, 10 Nov 2014 23:52:26 +0100 Subject: [PATCH] Timeout should not trigger a retry by default --- Changelog.rst | 6 ++++++ elasticsearch/connection/http_urllib3.py | 6 +++--- elasticsearch/transport.py | 18 ++++++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Changelog.rst b/Changelog.rst index fe2f3eba..a4d0a589 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -3,6 +3,12 @@ Changelog ========= +1.3.0 (dev) +----------- + + * Timeout now doesn't trigger a retry by default (can be overriden by setting + `retry_on_timeout=True`) + 1.2.0 (2014-08-03) ------------------ diff --git a/elasticsearch/connection/http_urllib3.py b/elasticsearch/connection/http_urllib3.py index 430154b9..68207d7b 100644 --- a/elasticsearch/connection/http_urllib3.py +++ b/elasticsearch/connection/http_urllib3.py @@ -3,7 +3,7 @@ import urllib3 from urllib3.exceptions import ReadTimeoutError from .base import Connection -from ..exceptions import ConnectionError +from ..exceptions import ConnectionError, ConnectionTimeout from ..compat import urlencode class Urllib3HttpConnection(Connection): @@ -33,7 +33,7 @@ class Urllib3HttpConnection(Connection): def perform_request(self, method, url, params=None, body=None, timeout=None, ignore=()): url = self.url_prefix + url if params: - url = '%s?%s' % (url, urlencode(params or {})) + url = '%s?%s' % (url, urlencode(params)) full_url = self.host + url start = time.time() @@ -52,7 +52,7 @@ class Urllib3HttpConnection(Connection): raw_data = response.data.decode('utf-8') except ReadTimeoutError as e: self.log_request_fail(method, full_url, body, time.time() - start, exception=e) - raise ConnectionError('TIMEOUT', str(e), e) + raise ConnectionTimeout('TIMEOUT', str(e), e) except Exception as e: self.log_request_fail(method, full_url, body, time.time() - start, exception=e) raise ConnectionError('N/A', str(e), e) diff --git a/elasticsearch/transport.py b/elasticsearch/transport.py index 54dbb2eb..78663072 100644 --- a/elasticsearch/transport.py +++ b/elasticsearch/transport.py @@ -4,7 +4,8 @@ import time from .connection import Urllib3HttpConnection from .connection_pool import ConnectionPool from .serializer import JSONSerializer, Deserializer, DEFAULT_SERIALIZERS -from .exceptions import ConnectionError, TransportError, SerializationError +from .exceptions import ConnectionError, TransportError, SerializationError, \ + ConnectionTimeout # get ip/port from "inet[wind/127.0.0.1:9200]" ADDRESS_RE = re.compile(r'/(?P[\.:0-9a-f]*):(?P[0-9]+)\]?$') @@ -45,7 +46,7 @@ class Transport(object): sniff_on_start=False, sniffer_timeout=None, sniff_timeout=.1, sniff_on_connection_fail=False, serializer=JSONSerializer(), serializers=None, default_mimetype='application/json', max_retries=3, - send_get_body_as='GET', **kwargs): + retry_on_timeout=False, send_get_body_as='GET', **kwargs): """ :arg hosts: list of dictionaries, each containing keyword arguments to create a `connection_class` instance @@ -67,6 +68,8 @@ class Transport(object): :arg default_mimetype: when no mimetype is specified by the server response assume this mimetype, defaults to `'application/json'` :arg max_retries: maximum number of retries before an exception is propagated + :arg retry_on_timeout: should timeout trigger a retry on different + node? (default `False`) :arg send_get_body_as: for GET requests with body this option allows you to specify an alternate way of execution for environments that don't support passing bodies with GET requests. If you set this to @@ -89,6 +92,7 @@ class Transport(object): self.deserializer = Deserializer(_serializers, default_mimetype) self.max_retries = max_retries + self.retry_on_timeout = retry_on_timeout self.send_get_body_as = send_get_body_as # data serializer @@ -282,6 +286,16 @@ class Transport(object): try: status, headers, data = connection.perform_request(method, url, params, body, ignore=ignore, timeout=timeout) + except ConnectionTimeout: + if self.retry_on_timeout: + # only mark as dead if we are retrying + self.mark_dead(connection) + # raise exception on last retry + if attempt == self.max_retries: + raise + else: + raise + except ConnectionError: self.mark_dead(connection)