Skip to content

Commit f49ed55

Browse files
authored
feat(tableau): implement exponential backoff for retry logic on InternalServerError (#15828)
1 parent b21d900 commit f49ed55

File tree

3 files changed

+370
-2
lines changed

3 files changed

+370
-2
lines changed

metadata-ingestion/src/datahub/ingestion/source/tableau/tableau.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,16 @@ def get_connection_object_page(
14791479
# will be thrown, and we need to re-authenticate and retry.
14801480
self._re_authenticate()
14811481

1482+
# Add exponential backoff to avoid hammering the server
1483+
backoff_time = min(
1484+
(self.config.max_retries - retries_remaining + 1) ** 2, 60
1485+
)
1486+
logger.info(
1487+
f"Retrying query due to {e.__class__.__name__} with {retries_remaining} retries remaining, "
1488+
f"will retry in {backoff_time} seconds"
1489+
)
1490+
time.sleep(backoff_time)
1491+
14821492
return self.get_connection_object_page(
14831493
query=query,
14841494
connection_type=connection_type,
@@ -1496,7 +1506,17 @@ def get_connection_object_page(
14961506
if ise.code in RETRIABLE_ERROR_CODES:
14971507
if retries_remaining <= 0:
14981508
raise ise
1499-
logger.info(f"Retrying query due to error {ise.code}")
1509+
1510+
# Add exponential backoff to avoid hammering the server
1511+
backoff_time = min(
1512+
(self.config.max_retries - retries_remaining + 1) ** 2, 60
1513+
)
1514+
logger.info(
1515+
f"Retrying query due to error {ise.code} with {retries_remaining} retries remaining, "
1516+
f"will retry in {backoff_time} seconds"
1517+
)
1518+
time.sleep(backoff_time)
1519+
15001520
return self.get_connection_object_page(
15011521
query=query,
15021522
connection_type=connection_type,
@@ -1519,6 +1539,17 @@ def get_connection_object_page(
15191539
# retry logic is basically a bandaid for that.
15201540
if retries_remaining <= 0:
15211541
raise
1542+
1543+
# Add exponential backoff to avoid hammering the server
1544+
backoff_time = min(
1545+
(self.config.max_retries - retries_remaining + 1) ** 2, 60
1546+
)
1547+
logger.info(
1548+
f"Retrying query due to OSError with {retries_remaining} retries remaining, "
1549+
f"will retry in {backoff_time} seconds"
1550+
)
1551+
time.sleep(backoff_time)
1552+
15221553
return self.get_connection_object_page(
15231554
query=query,
15241555
connection_type=connection_type,

metadata-ingestion/tests/integration/tableau/test_tableau_ingest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,9 +1148,11 @@ def test_retry_on_error(pytestconfig, tmp_path, mock_datahub_graph):
11481148
mock_sdk.return_value = mock_client
11491149

11501150
reporter = TableauSourceReport()
1151+
mock_config = mock.MagicMock()
1152+
mock_config.max_retries = 3 # Set max_retries for backoff calculation
11511153
tableau_source = TableauSiteSource(
11521154
platform="tableau",
1153-
config=mock.MagicMock(),
1155+
config=mock_config,
11541156
ctx=mock.MagicMock(),
11551157
site=mock.MagicMock(spec=SiteItem, id="Site1", content_url="site1"),
11561158
server=mock_sdk.return_value,

0 commit comments

Comments
 (0)