Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix retry logic failures #5137

Merged
merged 5 commits into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/unreleased/Fixes-20220422-131227.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Fixes
body: Fix retry logic to return values after initial try
time: 2022-04-22T13:12:27.239055-05:00
custom:
Author: emmyoop
Issue: "5023"
PR: "5137"
2 changes: 1 addition & 1 deletion core/dbt/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ def _connection_exception_retry(fn, max_attempts: int, attempt: int = 0):
fire_event(RecordRetryException(exc=exc))
fire_event(RetryExternalCall(attempt=attempt, max=max_attempts))
time.sleep(1)
_connection_exception_retry(fn, max_attempts, attempt + 1)
return _connection_exception_retry(fn, max_attempts, attempt + 1)
else:
raise ConnectionException("External connection exception occurred: " + str(exc))

Expand Down
59 changes: 59 additions & 0 deletions tests/unit/test_connection_retries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import functools
import pytest
from requests.exceptions import RequestException
from dbt.exceptions import ConnectionException
from dbt.utils import _connection_exception_retry


def no_retry_fn():
return "success"


class TestNoRetries:
def test_no_retry(self):
fn_to_retry = functools.partial(no_retry_fn)
result = _connection_exception_retry(fn_to_retry, 3)

expected = "success"

assert result == expected


def no_success_fn():
raise RequestException("You'll never pass")
return "failure"


class TestMaxRetries:
def test_no_retry(self):
fn_to_retry = functools.partial(no_success_fn)

with pytest.raises(ConnectionException):
_connection_exception_retry(fn_to_retry, 3)


def single_retry_fn():
global counter
if counter == 0:
counter += 1
raise RequestException("You won't pass this one time")
elif counter == 1:
counter += 1
return "success on 2"

return "How did we get here?"


class TestSingleRetry:
def test_no_retry(self):
global counter
counter = 0

fn_to_retry = functools.partial(single_retry_fn)
result = _connection_exception_retry(fn_to_retry, 3)
expected = "success on 2"

# We need to test the return value here, not just that it did not throw an error.
# If the value is not being passed it causes cryptic errors
assert result == expected
assert counter == 2