Skip to content

Commit fa1fd50

Browse files
committed
Revert all changes since main
Signed-off-by: Jesse Whitehouse <[email protected]>
1 parent 7474834 commit fa1fd50

File tree

3 files changed

+13
-178
lines changed

3 files changed

+13
-178
lines changed

src/databricks/sql/thrift_backend.py

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import threading
66
from uuid import uuid4
77
from ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED, create_default_context
8-
import socket, types
98

109
import pyarrow
1110
import thrift.transport.THttpClient
@@ -40,7 +39,6 @@
4039
"_retry_delay_max": (float, 60, 5, 3600),
4140
"_retry_stop_after_attempts_count": (int, 30, 1, 60),
4241
"_retry_stop_after_attempts_duration": (float, 900, 1, 86400),
43-
"_retry_delay_default": (float, 5, 1, 60),
4442
}
4543

4644

@@ -81,8 +79,6 @@ def __init__(
8179
# next calculated pre-retry delay would go past
8280
# _retry_stop_after_attempts_duration, stop now.)
8381
#
84-
# _retry_delay_default (default: 5)
85-
# used when Retry-After is not specified by the server
8682
# _retry_stop_after_attempts_count
8783
# The maximum number of times we should retry retryable requests (defaults to 24)
8884
# _socket_timeout
@@ -247,7 +243,7 @@ def _handle_request_error(self, error_info, attempt, elapsed):
247243
# FUTURE: Consider moving to https://github.com/litl/backoff or
248244
# https://github.com/jd/tenacity for retry logic.
249245
def make_request(self, method, request):
250-
"""Execute given request, attempting retries when TCP connection fils or when receiving HTTP 429/503.
246+
"""Execute given request, attempting retries when receiving HTTP 429/503.
251247
252248
For delay between attempts, honor the given Retry-After header, but with bounds.
253249
Use lower bound of expontial-backoff based on _retry_delay_min,
@@ -265,12 +261,8 @@ def get_elapsed():
265261
return time.time() - t0
266262

267263
def extract_retry_delay(attempt):
268-
"""
269-
Encapsulate retry checks based on HTTP headers. Returns None || delay-in-secs
270-
271-
Retry IFF 429/503 code + Retry-After header set
272-
"""
273-
264+
# encapsulate retry checks, returns None || delay-in-secs
265+
# Retry IFF 429/503 code + Retry-After header set
274266
http_code = getattr(self._transport, "code", None)
275267
retry_after = getattr(self._transport, "headers", {}).get("Retry-After")
276268
if http_code in [429, 503] and retry_after:
@@ -287,63 +279,24 @@ def attempt_request(attempt):
287279
# - non-None method_return -> success, return and be done
288280
# - non-None retry_delay -> sleep delay before retry
289281
# - error, error_message always set when available
290-
291-
error = None
292-
293-
# If retry_delay is None the request is treated as non-retryable
294-
retry_delay = None
295282
try:
296283
logger.debug("Sending request: {}".format(request))
297284
response = method(request)
298285
logger.debug("Received response: {}".format(response))
299286
return response
300-
except socket.timeout as err:
301-
# We only retry for socket.timeout if the operation that timed out was a connection request
302-
# Otherwise idempotency is not guaranteed because something may have been transmitted to the server
303-
304-
def _dig_through_traceback(tb: types.TracebackType, mod, meth):
305-
"""Recursively search the traceback stack to see if mod.meth raised the exception
306-
"""
307-
_mod, _meth = mod, meth
308-
tb_meth = tb.tb_frame.f_code.co_name
309-
tb_mod = tb.tb_frame.f_code.co_filename.split("/")[-1].replace(".py", "")
310-
311-
if tb_meth == _meth and _mod == tb_mod:
312-
return True
313-
elif tb.tb_next is None:
314-
return False
315-
316-
return _dig_through_traceback(tb.tb_next, mod, meth)
317-
318-
tb = err.__traceback__
319-
failed_during_socket_connect = _dig_through_traceback(tb, "socket", "create_connection")
320-
failed_during_http_open = _dig_through_traceback(tb, "client", "connect")
321-
322-
if failed_during_socket_connect and failed_during_http_open:
323-
retry_delay = self._retry_delay_default
324-
325-
error_message = str(err)
326-
error = err
327-
except OSError as err:
328-
# OSError 110 means EHOSTUNREACHABLE, which means the connection was timed out by the operating system
329-
if "Errno 110" in str(err):
330-
retry_delay = self._retry_delay_default
331-
error_message = str(err)
332-
error = err
333-
except Exception as err:
287+
except Exception as error:
334288
retry_delay = extract_retry_delay(attempt)
335289
error_message = ThriftBackend._extract_error_message_from_headers(
336290
getattr(self._transport, "headers", {})
337291
)
338-
error = err
339-
return RequestErrorInfo(
340-
error=error,
341-
error_message=error_message,
342-
retry_delay=retry_delay,
343-
http_code=getattr(self._transport, "code", None),
344-
method=method.__name__,
345-
request=request,
346-
)
292+
return RequestErrorInfo(
293+
error=error,
294+
error_message=error_message,
295+
retry_delay=retry_delay,
296+
http_code=getattr(self._transport, "code", None),
297+
method=method.__name__,
298+
request=request,
299+
)
347300

348301
# The real work:
349302
# - for each available attempt:

tests/e2e/driver_tests.py

Lines changed: 1 addition & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
import threading
99
import time
10-
from unittest import loader, skipIf, skipUnless, TestCase, mock
10+
from unittest import loader, skipIf, skipUnless, TestCase
1111
from uuid import uuid4
1212

1313
import numpy as np
@@ -360,66 +360,6 @@ def execute_really_long_query():
360360
cursor.execute("SELECT * FROM range(3)")
361361
self.assertEqual(len(cursor.fetchall()), 3)
362362

363-
def test_retry_after_connection_timeout(self):
364-
# We only retry a request that failed because of a socket timeout in this case
365-
# when the timeout occurred while trying to connect with the thrift server.
366-
# In this situation, we know that a command was not sent to the server because
367-
# no connection was made.
368-
369-
import socket
370-
from unittest.mock import Mock
371-
from databricks.sql.thrift_api.TCLIService import ttypes
372-
373-
# First let's check the non-retry behavior
374-
# Given the client has successfully connected to the server already
375-
# When a socket.timeout exception is raised
376-
# Then the request is not retried
377-
with self.assertRaises(OperationalError) as cm:
378-
379-
# No mocks at this point. If calling self.cursor() succeeds
380-
# that means there is an open / working connection to thrift server.
381-
with self.cursor({}) as cursor:
382-
383-
# Next apply a patch to the transport which raises a socket.timeout
384-
# whenever any data is sent over the wire
385-
with mock.patch("http.client.HTTPConnection.send") as mock_send:
386-
mock_send.side_effect = socket.timeout
387-
cursor.execute("I AM A VERY DANGEROUS, NOT IDEMPOTENT QUERY!!!")
388-
self.assertIn("non-retryable error", cm.exception.message_with_context())
389-
390-
391-
# Second, let's check whether a request is retried if it fails during
392-
# the connection attempt, instead of the send attempt.
393-
394-
ATTEMPTS_TO_TRY = 2
395-
396-
# This is a normal query execution
397-
# with self.cursor({}) as cursor:
398-
# thrift_backend = cursor.thrift_backend
399-
400-
401-
with self.assertRaises(OperationalError) as cm:
402-
with mock.patch("socket.socket.connect") as mock_connect:
403-
mock_connect.side_effect = OSError("[Errno 110]: Connection timed out")
404-
with self.cursor() as cursor:
405-
# Connection will fail
406-
cursor.execute("SOME RANDOM STATEMENT")
407-
pass
408-
409-
self.assertIn("{0}/{0}".format(ATTEMPTS_TO_TRY), cm.exception.message_with_context())
410-
411-
with self.assertRaises(OperationalError) as cm:
412-
with mock.patch("socket.socket.connect") as mock_connect:
413-
mock_connect.side_effect = socket.timeout
414-
with self.cursor() as cursor:
415-
# Connection will fail
416-
cursor.execute("SOME RANDOM STATEMENT")
417-
pass
418-
419-
self.assertIn("{0}/{0}".format(ATTEMPTS_TO_TRY), cm.exception.message_with_context())
420-
421-
422-
423363
@skipIf(pysql_has_version('<', '2'), 'requires pysql v2')
424364
def test_can_execute_command_after_failure(self):
425365
with self.cursor({}) as cursor:

tests/unit/test_thrift_backend.py

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ def retry_policy_factory():
1919
"_retry_delay_max": (float, 60, None, None),
2020
"_retry_stop_after_attempts_count": (int, 30, None, None),
2121
"_retry_stop_after_attempts_duration": (float, 900, None, None),
22-
"_retry_delay_default": (float, 5, 0, 10),
2322
}
2423

2524

@@ -985,63 +984,6 @@ def test_make_request_wont_retry_if_headers_not_present(self, t_transport_class)
985984

986985
self.assertIn("This method fails", str(cm.exception.message_with_context()))
987986

988-
@patch("thrift.transport.THttpClient.THttpClient")
989-
def test_will_retry_on_connection_timeout(self, t_transport_class):
990-
991-
import socket
992-
993-
mock_method = Mock()
994-
mock_method.__name__ = "method name"
995-
mock_method.side_effect = socket.timeout
996-
997-
thrift_backend = ThriftBackend(
998-
"foobar",
999-
443,
1000-
"path",
1001-
[],
1002-
_retry_stop_after_attempts_count=2,
1003-
_retry_delay_default=0.25
1004-
)
1005-
1006-
with self.assertRaises(OperationalError) as cm:
1007-
thrift_backend.make_request(mock_method, Mock())
1008-
1009-
self.assertIn("2/2", cm.exception.message_with_context())
1010-
1011-
mock_method = Mock()
1012-
mock_method.__name__ = "method name"
1013-
mock_method.side_effect = OSError("[Errno 110] Connection timed out")
1014-
1015-
with self.assertRaises(OperationalError) as cm:
1016-
thrift_backend.make_request(mock_method, Mock())
1017-
1018-
self.assertIn("2/2", cm.exception.message_with_context())
1019-
1020-
@patch("thrift.transport.THttpClient.THttpClient")
1021-
def test_will_not_retry_on_non_timeout_oserror(self, t_transport_class):
1022-
1023-
1024-
1025-
mock_method = Mock()
1026-
mock_method.__name__ = "method name"
1027-
mock_method.side_effect = OSError("I am not a timeout error")
1028-
1029-
thrift_backend = ThriftBackend(
1030-
"foobar",
1031-
443,
1032-
"path",
1033-
[],
1034-
_retry_stop_after_attempts_count=2,
1035-
_retry_delay_default=0.25
1036-
)
1037-
1038-
with self.assertRaises(OperationalError) as cm:
1039-
thrift_backend.make_request(mock_method, Mock())
1040-
1041-
self.assertIn("I am not a timeout error", str(cm.exception.message_with_context()))
1042-
self.assertIn("1/2", cm.exception.message_with_context())
1043-
1044-
1045987
@patch("thrift.transport.THttpClient.THttpClient")
1046988
def test_make_request_wont_retry_if_error_code_not_429_or_503(self, t_transport_class):
1047989
t_transport_instance = t_transport_class.return_value

0 commit comments

Comments
 (0)