Skip to content

Commit 38411a8

Browse files
committed
Log when a request is retried due to an OSError.
Emit warnings for unexpected OSError codes Signed-off-by: Jesse Whitehouse <[email protected]>
1 parent a55cf9d commit 38411a8

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

src/databricks/sql/thrift_backend.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from decimal import Decimal
2+
import errno
23
import logging
34
import math
45
import time
@@ -304,6 +305,27 @@ def attempt_request(attempt):
304305
gos_name = TCLIServiceClient.GetOperationStatus.__name__
305306
if method.__name__ == gos_name:
306307
retry_delay = bound_retry_delay(attempt, self._retry_delay_default)
308+
309+
# fmt: off
310+
# The built-in errno package encapsulates OSError codes, which are OS-specific.
311+
# log.info for errors we believe are not unusual or unexpected. log.warn for
312+
# for others like EEXIST, EBADF, ERANGE which are not expected in this context.
313+
# | Debian | Darwin |
314+
info_errs = [ # |--------|--------|
315+
errno.ESHUTDOWN, # | 32 | 32 |
316+
errno.EAFNOSUPPORT, # | 97 | 47 |
317+
errno.ECONNRESET, # | 104 | 54 |
318+
errno.ETIMEDOUT, # | 110 | 60 |
319+
]
320+
321+
# fmt: on
322+
log_string = (
323+
f"{gos_name} failed with code {err.errno} and will attempt to retry"
324+
)
325+
if err.errno in info_errs:
326+
logger.info(log_string)
327+
else:
328+
logger.warning(log_string)
307329
except Exception as err:
308330
error = err
309331
retry_delay = extract_retry_delay(attempt)

tests/unit/test_thrift_backend.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -975,13 +975,14 @@ def test_handle_execute_response_sets_active_op_handle(self):
975975
def test_make_request_will_retry_GetOperationStatus(
976976
self, mock_retry_policy, mock_GetOperationStatus, t_transport_class):
977977

978-
import thrift
978+
import thrift, errno
979979
from databricks.sql.thrift_api.TCLIService.TCLIService import Client
980980
from databricks.sql.exc import RequestError
981981
from databricks.sql.utils import NoRetryReason
982982

983-
mock_GetOperationStatus.__name__ = "GetOperationStatus"
984-
mock_GetOperationStatus.side_effect = TimeoutError(110)
983+
this_gos_name = "GetOperationStatus"
984+
mock_GetOperationStatus.__name__ = this_gos_name
985+
mock_GetOperationStatus.side_effect = OSError(errno.ETIMEDOUT, "Connection timed out")
985986

986987
protocol = thrift.protocol.TBinaryProtocol.TBinaryProtocol(t_transport_class)
987988
client = Client(protocol)
@@ -998,13 +999,30 @@ def test_make_request_will_retry_GetOperationStatus(
998999
443,
9991000
"path", [],
10001001
_retry_stop_after_attempts_count=EXPECTED_RETRIES,
1001-
_retry_delay_default=0.1)
1002+
_retry_delay_default=1)
1003+
10021004

10031005
with self.assertRaises(RequestError) as cm:
10041006
thrift_backend.make_request(client.GetOperationStatus, req)
10051007

10061008
self.assertEqual(NoRetryReason.OUT_OF_ATTEMPTS.value, cm.exception.context["no-retry-reason"])
1007-
self.assertEqual(f'{EXPECTED_RETRIES}/{EXPECTED_RETRIES}', cm.exception.context["attempt"])
1009+
self.assertEqual(f'{EXPECTED_RETRIES}/{EXPECTED_RETRIES}', cm.exception.context["attempt"])
1010+
1011+
# Unusual OSError code
1012+
mock_GetOperationStatus.side_effect = OSError(errno.EEXIST, "File does not exist")
1013+
1014+
with self.assertLogs("databricks.sql.thrift_backend", level=logging.WARNING) as cm:
1015+
with self.assertRaises(RequestError):
1016+
thrift_backend.make_request(client.GetOperationStatus, req)
1017+
1018+
# There should be two warning log messages: one for each retry
1019+
self.assertEqual(len(cm.output), EXPECTED_RETRIES)
1020+
1021+
# The warnings should be identical
1022+
self.assertEqual(cm.output[1], cm.output[0])
1023+
1024+
# The warnings should include this text
1025+
self.assertIn(f"{this_gos_name} failed with code {errno.EEXIST} and will attempt to retry", cm.output[0])
10081026

10091027

10101028
@patch("thrift.transport.THttpClient.THttpClient")

0 commit comments

Comments
 (0)