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] = [

Reply via email to