Skip to content

Commit

Permalink
replace our custom list of retryable exceptions with BigQuery's defau…
Browse files Browse the repository at this point in the history
…lts; keep BadRequest as retryable as that is not in BigQuery's defaults and could cause a breaking change by removing it
  • Loading branch information
mikealfare committed Dec 11, 2024
1 parent 89766ae commit 5900683
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 17 deletions.
24 changes: 8 additions & 16 deletions dbt/adapters/bigquery/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from google.api_core.exceptions import Forbidden
from google.api_core.future.polling import DEFAULT_POLLING
from google.api_core.retry import Retry
from google.cloud.bigquery.retry import DEFAULT_RETRY
from google.cloud.exceptions import BadGateway, BadRequest, ServerError
from google.cloud.bigquery.retry import DEFAULT_RETRY, _job_should_retry
from google.cloud.exceptions import BadRequest
from requests.exceptions import ConnectionError

from dbt.adapters.contracts.connection import Connection, ConnectionState
Expand Down Expand Up @@ -74,6 +74,11 @@ def __init__(self, retries: int) -> None:
self._retries: int = retries
self._error_count = 0

@staticmethod
def _is_retryable(error: Exception) -> bool:
"""Return true for errors that are unlikely to occur again if retried."""
return _job_should_retry(error) or isinstance(error, BadRequest)

def __call__(self, error: Exception) -> bool:
# exit immediately if the user does not want retries
if self._retries == 0:
Expand All @@ -83,7 +88,7 @@ def __call__(self, error: Exception) -> bool:
self._error_count += 1

# if the error is retryable, and we haven't breached the threshold, log and continue
if _is_retryable(error) and self._error_count <= self._retries:
if self._is_retryable(error) and self._error_count <= self._retries:
_logger.debug(
f"Retry attempt {self._error_count} of {self._retries} after error: {repr(error)}"
)
Expand Down Expand Up @@ -113,16 +118,3 @@ def on_error(error: Exception):
raise FailedToConnectError(str(e))

return on_error


def _is_retryable(error: Exception) -> bool:
"""Return true for errors that are unlikely to occur again if retried."""
if isinstance(
error, (BadGateway, BadRequest, ConnectionError, ConnectionResetError, ServerError)
):
return True
elif isinstance(error, Forbidden) and any(
e["reason"] == "rateLimitExceeded" for e in error.errors
):
return True
return False
2 changes: 1 addition & 1 deletion tests/unit/test_bigquery_connection_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def generate_connection_reset_error():
assert new_mock_client is not self.mock_client

def test_is_retryable(self):
_is_retryable = dbt.adapters.bigquery.retry._is_retryable
_is_retryable = dbt.adapters.bigquery.retry._DeferredException(1)._is_retryable
exceptions = dbt.adapters.bigquery.impl.google.cloud.exceptions
internal_server_error = exceptions.InternalServerError("code broke")
bad_request_error = exceptions.BadRequest("code broke")
Expand Down

0 comments on commit 5900683

Please sign in to comment.