This is an automated email from the ASF dual-hosted git repository.
Lee-W pushed a commit to branch airflow-ctl/v0-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/airflow-ctl/v0-1-test by this
push:
new b57e652754a [airflow-ctl/v0-1-test] Log the retry reason in airflowctl
API client retries (#75059) (#75198)
b57e652754a is described below
commit b57e652754a16c88e2dca87b3200753a31234494
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Tue Oct 20 17:10:53 2026 +0800
[airflow-ctl/v0-1-test] Log the retry reason in airflowctl API client
retries (#75059) (#75198)
Co-authored-by: W. H. Wang <[email protected]>
---
airflow-ctl/src/airflowctl/api/client.py | 4 +--
airflow-ctl/tests/airflow_ctl/api/test_client.py | 31 ++++++++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/airflow-ctl/src/airflowctl/api/client.py
b/airflow-ctl/src/airflowctl/api/client.py
index 11fc0b487c9..e0fcf1dfbed 100644
--- a/airflow-ctl/src/airflowctl/api/client.py
+++ b/airflow-ctl/src/airflowctl/api/client.py
@@ -35,7 +35,7 @@ import structlog
from httpx import URL
from keyring.errors import NoKeyringError
from tenacity import (
- before_log,
+ before_sleep_log,
retry,
retry_if_exception,
stop_after_attempt,
@@ -398,7 +398,7 @@ class Client(httpx.Client):
retry=retry_if_exception(_should_retry_api_request),
stop=stop_after_attempt(API_RETRIES),
wait=wait_random_exponential(min=API_RETRY_WAIT_MIN,
max=API_RETRY_WAIT_MAX),
- before_sleep=before_log(log, logging.WARNING),
+ before_sleep=before_sleep_log(log, logging.WARNING),
reraise=True,
)
def request(self, *args, **kwargs):
diff --git a/airflow-ctl/tests/airflow_ctl/api/test_client.py
b/airflow-ctl/tests/airflow_ctl/api/test_client.py
index 22fc749222d..a4318951fb8 100644
--- a/airflow-ctl/tests/airflow_ctl/api/test_client.py
+++ b/airflow-ctl/tests/airflow_ctl/api/test_client.py
@@ -27,6 +27,8 @@ from unittest.mock import MagicMock, patch
import httpx
import pytest
+import structlog.testing
+import tenacity
import time_machine
from httpx import URL
@@ -455,6 +457,35 @@ class TestSaveKeyringPatching:
assert response.status_code == 200
assert len(responses) == 1
+ @patch("airflowctl.api.client.Client.request.retry.wait",
tenacity.wait_fixed(2))
+ @patch("airflowctl.api.client.Client.request.retry.sleep", autospec=True)
+ def test_retry_logs_error_and_wait_before_sleep(self, mock_sleep):
+ outcomes: list[httpx.Response | httpx.ConnectError] = [
+ httpx.ConnectError("Connection refused"),
+ httpx.Response(200, json={"detail": "Recovered from error"}),
+ ]
+
+ def handle_request(request: httpx.Request) -> httpx.Response:
+ outcome = outcomes.pop(0)
+ if isinstance(outcome, httpx.ConnectError):
+ raise outcome
+ return outcome
+
+ client = Client(base_url="", token="",
transport=httpx.MockTransport(handle_request))
+
+ with structlog.testing.capture_logs() as captured_logs:
+ response = client.get("http://error")
+
+ assert response.status_code == 200
+ mock_sleep.assert_called_once_with(2)
+ assert [(entry["log_level"], entry["event"]) for entry in
captured_logs] == [
+ (
+ "warning",
+ "Retrying airflowctl.api.client.Client.request in 2 seconds "
+ "as it raised ConnectError: Connection refused.",
+ )
+ ]
+
def test_retry_handling_non_retry_error(self):
with time_machine.travel("2023-01-01T00:00:00Z", tick=False):
responses: list[httpx.Response] = [