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

potiuk 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 f74a685978c Use configured default queue for Celery executor callbacks 
(#73552)
f74a685978c is described below

commit f74a685978c1048e115c94abde445075089b3953
Author: ccoliu <[email protected]>
AuthorDate: Mon Oct 5 08:22:29 2026 +0800

    Use configured default queue for Celery executor callbacks (#73552)
    
    CeleryExecutor hardcoded the "default" queue when dispatching
    ExecuteCallback workloads, ignoring [operators] default_queue. In
    deployments without a Celery queue named "default", deadline
    SyncCallbacks were never picked up by a worker.
    
    Read the queue from the executor's (team-aware) config, matching how the
    Edge executor routes callbacks. A queue set in the callback data still
    takes precedence.
    
    closes: #73545
    
    Co-authored-by: Claude Opus 5 <[email protected]>
---
 .../providers/celery/executors/celery_executor.py  |  4 +--
 .../unit/celery/executors/test_celery_executor.py  | 29 ++++++++++++++++++----
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git 
a/providers/celery/src/airflow/providers/celery/executors/celery_executor.py 
b/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
index 68304cdbea0..91d7509da25 100644
--- a/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
+++ b/providers/celery/src/airflow/providers/celery/executors/celery_executor.py
@@ -191,8 +191,8 @@ class CeleryExecutor(BaseExecutor):
                 key = self.get_task_key(workload.ti) if 
self.supports_task_instance_uuid else workload.ti.key
                 workloads_to_be_sent.append((key, workload, workload.ti.queue, 
self.team_name))
             elif AIRFLOW_V_3_2_PLUS and isinstance(workload, ExecuteCallback):
-                # Use default queue for callbacks, or extract from callback 
data if available.
-                queue = "default"
+                # Use the configured default queue for callbacks, or extract 
from callback data if available.
+                queue = self.conf.get_mandatory_value("operators", 
"default_queue")
                 if isinstance(workload.callback.data, dict) and "queue" in 
workload.callback.data:
                     queue = workload.callback.data["queue"]
                 workloads_to_be_sent.append((workload.callback.key, workload, 
queue, self.team_name))
diff --git 
a/providers/celery/tests/unit/celery/executors/test_celery_executor.py 
b/providers/celery/tests/unit/celery/executors/test_celery_executor.py
index 4579fa436eb..bbd1493b32f 100644
--- a/providers/celery/tests/unit/celery/executors/test_celery_executor.py
+++ b/providers/celery/tests/unit/celery/executors/test_celery_executor.py
@@ -1216,18 +1216,35 @@ def test_celery_tasks_registered_on_import():
 
 @pytest.mark.skipif(not AIRFLOW_V_3_2_PLUS, reason="ExecuteCallback requires 
Airflow 3.2+")
 @pytest.mark.parametrize(
-    ("callback_data", "expected_queue"),
+    ("callback_data", "configured_default_queue", "expected_queue"),
     [
-        pytest.param({"path": "tests.callbacks.test_callback", "kwargs": {}}, 
"default", id="default_queue"),
+        pytest.param(
+            {"path": "tests.callbacks.test_callback", "kwargs": {}}, None, 
"default", id="default_queue"
+        ),
         pytest.param(
             {"path": "tests.callbacks.test_callback", "kwargs": {}, "queue": 
"callback_queue"},
+            None,
             "callback_queue",
             id="callback_queue",
         ),
+        pytest.param(
+            {"path": "tests.callbacks.test_callback", "kwargs": {}},
+            "custom_default_queue",
+            "custom_default_queue",
+            id="configured_default_queue",
+        ),
+        pytest.param(
+            {"path": "tests.callbacks.test_callback", "kwargs": {}, "queue": 
"callback_queue"},
+            "custom_default_queue",
+            "callback_queue",
+            id="callback_queue_overrides_configured_default_queue",
+        ),
     ],
 )
 
@mock.patch("airflow.providers.celery.executors.celery_executor.CeleryExecutor._send_workloads")
-def test_process_workloads_routes_execute_callback(mock_send_workloads, 
callback_data, expected_queue):
+def test_process_workloads_routes_execute_callback(
+    mock_send_workloads, callback_data, configured_default_queue, 
expected_queue
+):
     """CeleryExecutor routes callback workloads to Celery with the expected 
queue."""
     from airflow.executors import workloads
     from airflow.executors.workloads.callback import CallbackDTO
@@ -1245,8 +1262,10 @@ def 
test_process_workloads_routes_execute_callback(mock_send_workloads, callback
         log_path="callback.log",
     )
 
-    executor = celery_executor.CeleryExecutor()
-    executor._process_workloads([workload])
+    config = {("operators", "default_queue"): configured_default_queue} if 
configured_default_queue else {}
+    with conf_vars(config):
+        executor = celery_executor.CeleryExecutor()
+        executor._process_workloads([workload])
 
     mock_send_workloads.assert_called_once_with([(workload.callback.key, 
workload, expected_queue, None)])
 

Reply via email to