This is an automated email from the ASF dual-hosted git repository.

amoghrajesh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 579aa9f0915 Reconnect to blocked Databricks runs in SubmitRunOperator 
durable retries (#69195)
579aa9f0915 is described below

commit 579aa9f0915d219667ddb2d34004b6fa7097d37c
Author: Amogh Desai <[email protected]>
AuthorDate: Wed Jul 1 14:17:29 2026 +0530

    Reconnect to blocked Databricks runs in SubmitRunOperator durable retries 
(#69195)
---
 .../providers/databricks/operators/databricks.py      |  9 ++++++++-
 .../unit/databricks/operators/test_databricks.py      | 19 +++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git 
a/providers/databricks/src/airflow/providers/databricks/operators/databricks.py 
b/providers/databricks/src/airflow/providers/databricks/operators/databricks.py
index 225bdf7595a..e9f2a016063 100644
--- 
a/providers/databricks/src/airflow/providers/databricks/operators/databricks.py
+++ 
b/providers/databricks/src/airflow/providers/databricks/operators/databricks.py
@@ -937,7 +937,14 @@ class DatabricksSubmitRunOperator(ResumableJobMixin, 
BaseOperator):
 
     def is_job_active(self, status: str) -> bool:
         life_cycle_state = status.split(":", 1)[0]
-        return life_cycle_state in ("PENDING", "QUEUED", "RUNNING", 
"TERMINATING")
+        return life_cycle_state in (
+            "PENDING",
+            "QUEUED",
+            "RUNNING",
+            "TERMINATING",
+            "BLOCKED",
+            "WAITING_FOR_RETRY",
+        )
 
     def is_job_succeeded(self, status: str) -> bool:
         return status == "TERMINATED:SUCCESS"
diff --git 
a/providers/databricks/tests/unit/databricks/operators/test_databricks.py 
b/providers/databricks/tests/unit/databricks/operators/test_databricks.py
index a0885ac48f4..ccf742338c0 100644
--- a/providers/databricks/tests/unit/databricks/operators/test_databricks.py
+++ b/providers/databricks/tests/unit/databricks/operators/test_databricks.py
@@ -1718,6 +1718,23 @@ class TestDatabricksSubmitRunOperatorDurable:
         task_store.set.assert_not_called()
         assert op.run_id == RUN_ID
 
+    
@mock.patch("airflow.providers.databricks.operators.databricks.DatabricksHook")
+    def test_reconnects_to_blocked_run_without_resubmitting(self, 
db_mock_class):
+        op = DatabricksSubmitRunOperator(
+            task_id=TASK_ID, json={"new_cluster": NEW_CLUSTER, 
"notebook_task": NOTEBOOK_TASK}
+        )
+        db_mock = db_mock_class.return_value
+        # A gated run sits in BLOCKED; the durable retry must reconnect and 
wait, not resubmit.
+        db_mock.get_run.side_effect = [self._state("BLOCKED"), 
self._state("TERMINATED", "SUCCESS")]
+        task_store = MagicMock(spec_set=["get", "set"])
+        task_store.get.return_value = RUN_ID
+
+        op.execute(self._context(task_store))
+
+        db_mock.submit_run.assert_not_called()
+        task_store.set.assert_not_called()
+        assert op.run_id == RUN_ID
+
     
@mock.patch("airflow.providers.databricks.operators.databricks._handle_databricks_operator_execution")
     
@mock.patch("airflow.providers.databricks.operators.databricks.DatabricksHook")
     def test_already_succeeded_pushes_xcoms_without_polling(self, 
db_mock_class, mock_poll):
@@ -1846,6 +1863,8 @@ class TestDatabricksSubmitRunOperatorDurable:
             ("PENDING:", True),
             ("QUEUED:", True),
             ("TERMINATING:", True),
+            ("BLOCKED:", True),
+            ("WAITING_FOR_RETRY:", True),
             ("TERMINATED:SUCCESS", False),
             ("TERMINATED:FAILED", False),
             ("SKIPPED:", False),

Reply via email to