Skip to content

Commit 0e16aae

Browse files
committed
Add request timeout
[ML-5598](https://iguazio.atlassian.net/browse/ML-5598)
1 parent 6e1942a commit 0e16aae

File tree

2 files changed

+34
-37
lines changed

2 files changed

+34
-37
lines changed

v3io/dataplane/kv_timestamp.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,14 @@
1919
BASE_DATETIME = datetime.datetime(1970, 1, 1)
2020

2121

22-
def _get_timestamp_from_datetime_py3(dt):
22+
def _get_timestamp_from_datetime(dt):
2323
return dt.astimezone(datetime.timezone.utc).timestamp()
2424

2525

2626
def _get_timestamp_from_datetime_py2(dt):
2727
return (dt - BASE_DATETIME).total_seconds()
2828

2929

30-
# _get_timestamp_from_datetime is python version specific. resolve this once
31-
if sys.version_info[0] >= 3:
32-
_get_timestamp_from_datetime = _get_timestamp_from_datetime_py3
33-
else:
34-
_get_timestamp_from_datetime = _get_timestamp_from_datetime_py2
35-
36-
3730
def encode(dt):
3831
timestamp = _get_timestamp_from_datetime(dt)
3932

v3io/dataplane/transport/httpclient.py

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525

2626

2727
class Transport(abstract.Transport):
28+
_connection_timeout_seconds = 20
29+
_request_max_retries = 2
30+
2831
def __init__(self, logger, endpoint=None, max_connections=None, timeout=None, verbosity=None):
2932
super(Transport, self).__init__(logger, endpoint, max_connections, timeout, verbosity)
3033

@@ -36,24 +39,19 @@ def __init__(self, logger, endpoint=None, max_connections=None, timeout=None, ve
3639
# create the pool connection
3740
self._create_connections(self.max_connections, self._host, self._ssl_context)
3841

39-
# python 2 and 3 have different exceptions
40-
if sys.version_info[0] >= 3:
41-
self._wait_response_exceptions = (
42-
http.client.RemoteDisconnected,
43-
ConnectionResetError,
44-
ConnectionRefusedError,
45-
http.client.ResponseNotReady,
46-
)
47-
self._send_request_exceptions = (
48-
BrokenPipeError,
49-
http.client.CannotSendRequest,
50-
http.client.RemoteDisconnected,
51-
)
52-
self._get_status_and_headers = self._get_status_and_headers_py3
53-
else:
54-
self._wait_response_exceptions = (http.client.BadStatusLine, socket.error)
55-
self._send_request_exceptions = (http.client.CannotSendRequest, http.client.BadStatusLine)
56-
self._get_status_and_headers = self._get_status_and_headers_py2
42+
self._wait_response_exceptions = (
43+
http.client.RemoteDisconnected,
44+
ConnectionResetError,
45+
ConnectionRefusedError,
46+
http.client.ResponseNotReady,
47+
)
48+
self._send_request_exceptions = (
49+
BrokenPipeError,
50+
http.client.CannotSendRequest,
51+
http.client.RemoteDisconnected,
52+
socket.timeout,
53+
)
54+
self._get_status_and_headers = self._get_status_and_headers_py3
5755

5856
def close(self):
5957
# Ignore redundant calls to close
@@ -154,20 +152,27 @@ def _send_request_on_connection(self, request, connection):
154152
self.log(
155153
"Tx", connection=connection, method=request.method, path=path, headers=request.headers, body=request.body
156154
)
155+
157156
starting_offset = 0
158157
is_body_seekable = request.body and hasattr(request.body, "seek") and hasattr(request.body, "tell")
159158
if is_body_seekable:
160159
starting_offset = request.body.tell()
161-
try:
160+
161+
retries_left = self._request_max_retries
162+
while True:
162163
try:
163164
connection.request(request.method, path, request.body, request.headers)
165+
break
164166
except self._send_request_exceptions as e:
165167
self._logger.debug_with(
166-
"Disconnected while attempting to send. Recreating connection and retrying",
168+
f"Disconnected while attempting to send request – "
169+
f"{retries_left} out of {self._request_max_retries} retries left.",
167170
e=type(e),
168171
e_msg=e,
169-
connection=connection,
170172
)
173+
if retries_left == 0:
174+
raise
175+
retries_left -= 1
171176
connection.close()
172177
if is_body_seekable:
173178
# If the first connection fails, the pointer of the body might move at the size
@@ -176,12 +181,11 @@ def _send_request_on_connection(self, request, connection):
176181
request.body.seek(starting_offset)
177182
connection = self._create_connection(self._host, self._ssl_context)
178183
request.transport.connection_used = connection
179-
connection.request(request.method, path, request.body, request.headers)
180-
except BaseException as e:
181-
self._logger.error_with(
182-
"Unhandled exception while sending request", e=type(e), e_msg=e, connection=connection
183-
)
184-
raise e
184+
except BaseException as e:
185+
self._logger.error_with(
186+
"Unhandled exception while sending request", e=type(e), e_msg=e, connection=connection
187+
)
188+
raise e
185189

186190
return request
187191

@@ -192,9 +196,9 @@ def _create_connections(self, num_connections, host, ssl_context):
192196

193197
def _create_connection(self, host, ssl_context):
194198
if ssl_context is None:
195-
return http.client.HTTPConnection(host)
199+
return http.client.HTTPConnection(host, timeout=self._connection_timeout_seconds)
196200

197-
return http.client.HTTPSConnection(host, context=ssl_context)
201+
return http.client.HTTPSConnection(host, timeout=self._connection_timeout_seconds, context=ssl_context)
198202

199203
def _parse_endpoint(self, endpoint):
200204
if endpoint.startswith("http://"):

0 commit comments

Comments
 (0)