Skip to content

Commit 871294e

Browse files
author
Jesse
authored
Convenience improvements to v3 retry logic (#199)
Signed-off-by: Jesse Whitehouse <[email protected]>
1 parent d28a692 commit 871294e

File tree

4 files changed

+45
-4
lines changed

4 files changed

+45
-4
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 2.9.x (Unreleased)
44

5+
- Other: Add `examples/v3_retries_query_execute.py`
6+
- Other: suppress log message when `_enable_v3_retries` is not `True`
7+
- Other: make this connector backwards compatible with `urllib3>=1.0.0`
8+
59
## 2.9.1 (2023-08-11)
610

711
- Other: Explicitly pin urllib3 to ^2.0.0

examples/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ To run all of these examples you can clone the entire repository to your disk. O
3838
this example the string `ExamplePartnerTag` will be added to the the user agent on every request.
3939
- **`staging_ingestion.py`** shows how the connector handles Databricks' experimental staging ingestion commands `GET`, `PUT`, and `REMOVE`.
4040
- **`sqlalchemy.py`** shows a basic example of connecting to Databricks with [SQLAlchemy](https://www.sqlalchemy.org/).
41-
- **`custom_cred_provider.py`** shows how to pass a custom credential provider to bypass connector authentication. Please install databricks-sdk prior to running this example.
41+
- **`custom_cred_provider.py`** shows how to pass a custom credential provider to bypass connector authentication. Please install databricks-sdk prior to running this example.
42+
- **`v3_retries_query_execute.py`** shows how to enable v3 retries in connector version 2.9.x including how to enable retries for non-default retry cases.

examples/v3_retries_query_execute.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from databricks import sql
2+
import os
3+
4+
# Users of connector versions >= 2.9.0 and <= 3.0.0 can use the v3 retry behaviour by setting _enable_v3_retries=True
5+
# This flag will be deprecated in databricks-sql-connector~=3.0.0 as it will become the default.
6+
#
7+
# The new retry behaviour is defined in src/databricks/sql/auth/retry.py
8+
#
9+
# The new retry behaviour allows users to force the connector to automatically retry requests that fail with codes
10+
# that are not retried by default (in most cases only codes 429 and 503 are retried by default). Additional HTTP
11+
# codes to retry are specified as a list passed to `_retry_dangerous_codes`.
12+
#
13+
# Note that, as implied in the name, doing this is *dangerous* and should not be configured in all usages.
14+
# With the default behaviour, ExecuteStatement Thrift commands are only retried for codes 429 and 503 because
15+
# we can be certain at run-time that the statement never reached Databricks compute. These codes are returned by
16+
# the SQL gateway / load balancer. So there is no risk that retrying the request would result in a doubled
17+
# (or tripled etc) command execution. These codes are always accompanied by a Retry-After header, which we honour.
18+
#
19+
# However, if your use-case emits idempotent queries such as SELECT statements, it can be helpful to retry
20+
# for 502 (Bad Gateway) codes etc. In these cases, there is a possibility that the initial command _did_ reach
21+
# Databricks compute and retrying it could result in additional executions. Retrying under these conditions uses
22+
# an exponential back-off since a Retry-After header is not present.
23+
24+
with sql.connect(server_hostname = os.getenv("DATABRICKS_SERVER_HOSTNAME"),
25+
http_path = os.getenv("DATABRICKS_HTTP_PATH"),
26+
access_token = os.getenv("DATABRICKS_TOKEN"),
27+
_enable_v3_retries = True,
28+
_retry_dangerous_codes=[502,400]) as connection:
29+
30+
with connection.cursor() as cursor:
31+
cursor.execute("SELECT * FROM default.diamonds LIMIT 2")
32+
result = cursor.fetchall()
33+
34+
for row in result:
35+
print(row)

src/databricks/sql/thrift_backend.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,10 @@ def attempt_request(attempt):
375375
unsafe_logger.debug("Sending request: {}".format(request))
376376

377377
# These three lines are no-ops if the v3 retry policy is not in use
378-
this_command_type = CommandType.get(this_method_name)
379-
self._transport.set_retry_command_type(this_command_type)
380-
self._transport.startRetryTimer()
378+
if self.enable_v3_retries:
379+
this_command_type = CommandType.get(this_method_name)
380+
self._transport.set_retry_command_type(this_command_type)
381+
self._transport.startRetryTimer()
381382

382383
response = method(request)
383384

0 commit comments

Comments
 (0)