Skip to content

Commit 0da1106

Browse files
guan404mingLee-W
andauthored
Update WorkflowTrigger to forward failed_stat (#50487)
* Update `external_task` to forward failed_stat * Apply suggestions from code review Co-authored-by: Wei Lee <weilee.rx@gmail.com> * Fix AF2 test --------- Co-authored-by: Wei Lee <weilee.rx@gmail.com>
1 parent 41f351c commit 0da1106

6 files changed

Lines changed: 356 additions & 55 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
"""Exceptions used by Standard Provider."""
18+
19+
from __future__ import annotations
20+
21+
from airflow.exceptions import AirflowException
22+
23+
24+
class AirflowExternalTaskSensorException(AirflowException):
25+
"""Base exception for all ExternalTaskSensor related errors."""
26+
27+
28+
class ExternalDagNotFoundError(AirflowExternalTaskSensorException):
29+
"""Raised when the external DAG does not exist."""
30+
31+
32+
class ExternalDagDeletedError(AirflowExternalTaskSensorException):
33+
"""Raised when the external DAG was deleted."""
34+
35+
36+
class ExternalTaskNotFoundError(AirflowExternalTaskSensorException):
37+
"""Raised when the external task does not exist."""
38+
39+
40+
class ExternalTaskGroupNotFoundError(AirflowExternalTaskSensorException):
41+
"""Raised when the external task group does not exist."""
42+
43+
44+
class ExternalTaskFailedError(AirflowExternalTaskSensorException):
45+
"""Raised when the external task failed."""
46+
47+
48+
class ExternalTaskGroupFailedError(AirflowExternalTaskSensorException):
49+
"""Raised when the external task group failed."""
50+
51+
52+
class ExternalDagFailedError(AirflowExternalTaskSensorException):
53+
"""Raised when the external DAG failed."""
54+
55+
56+
class DuplicateStateError(AirflowExternalTaskSensorException):
57+
"""Raised when duplicate states are provided across allowed, skipped and failed states."""

providers/standard/src/airflow/providers/standard/sensors/external_task.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#
21
# Licensed to the Apache Software Foundation (ASF) under one
32
# or more contributor license agreements. See the NOTICE file
43
# distributed with this work for additional information
@@ -24,9 +23,19 @@
2423
from typing import TYPE_CHECKING, Any, Callable, ClassVar
2524

2625
from airflow.configuration import conf
27-
from airflow.exceptions import AirflowException, AirflowSkipException
26+
from airflow.exceptions import AirflowSkipException
2827
from airflow.models.dag import DagModel
2928
from airflow.models.dagbag import DagBag
29+
from airflow.providers.standard.exceptions import (
30+
DuplicateStateError,
31+
ExternalDagDeletedError,
32+
ExternalDagFailedError,
33+
ExternalDagNotFoundError,
34+
ExternalTaskFailedError,
35+
ExternalTaskGroupFailedError,
36+
ExternalTaskGroupNotFoundError,
37+
ExternalTaskNotFoundError,
38+
)
3039
from airflow.providers.standard.operators.empty import EmptyOperator
3140
from airflow.providers.standard.triggers.external_task import WorkflowTrigger
3241
from airflow.providers.standard.utils.sensor_helper import _get_count, _get_external_task_group_task_ids
@@ -190,7 +199,7 @@ def __init__(
190199
total_states = set(self.allowed_states + self.skipped_states + self.failed_states)
191200

192201
if len(total_states) != len(self.allowed_states) + len(self.skipped_states) + len(self.failed_states):
193-
raise AirflowException(
202+
raise DuplicateStateError(
194203
"Duplicate values provided across allowed_states, skipped_states and failed_states."
195204
)
196205

@@ -356,7 +365,7 @@ def _handle_failed_states(self, count_failed: float | int) -> None:
356365
f"Some of the external tasks {self.external_task_ids} "
357366
f"in DAG {self.external_dag_id} failed. Skipping due to soft_fail."
358367
)
359-
raise AirflowException(
368+
raise ExternalTaskFailedError(
360369
f"Some of the external tasks {self.external_task_ids} "
361370
f"in DAG {self.external_dag_id} failed."
362371
)
@@ -366,15 +375,15 @@ def _handle_failed_states(self, count_failed: float | int) -> None:
366375
f"The external task_group '{self.external_task_group_id}' "
367376
f"in DAG '{self.external_dag_id}' failed. Skipping due to soft_fail."
368377
)
369-
raise AirflowException(
378+
raise ExternalTaskGroupFailedError(
370379
f"The external task_group '{self.external_task_group_id}' "
371380
f"in DAG '{self.external_dag_id}' failed."
372381
)
373382
if self.soft_fail:
374383
raise AirflowSkipException(
375384
f"The external DAG {self.external_dag_id} failed. Skipping due to soft_fail."
376385
)
377-
raise AirflowException(f"The external DAG {self.external_dag_id} failed.")
386+
raise ExternalDagFailedError(f"The external DAG {self.external_dag_id} failed.")
378387

379388
def _handle_skipped_states(self, count_skipped: float | int) -> None:
380389
"""Handle skipped states and raise appropriate exceptions."""
@@ -443,10 +452,14 @@ def execute_complete(self, context, event=None):
443452
self.log.info("External tasks %s has executed successfully.", self.external_task_ids)
444453
elif event["status"] == "skipped":
445454
raise AirflowSkipException("External job has skipped skipping.")
455+
elif event["status"] == "failed":
456+
if self.soft_fail:
457+
raise AirflowSkipException("External job has failed skipping.")
458+
raise ExternalDagFailedError("External job has failed.")
446459
else:
447460
if self.soft_fail:
448461
raise AirflowSkipException("External job has failed skipping.")
449-
raise AirflowException(
462+
raise ExternalTaskNotFoundError(
450463
"Error occurred while trying to retrieve task status. Please, check the "
451464
"name of executed task and Dag."
452465
)
@@ -455,23 +468,31 @@ def _check_for_existence(self, session) -> None:
455468
dag_to_wait = DagModel.get_current(self.external_dag_id, session)
456469

457470
if not dag_to_wait:
458-
raise AirflowException(f"The external DAG {self.external_dag_id} does not exist.")
471+
raise ExternalDagNotFoundError(f"The external DAG {self.external_dag_id} does not exist.")
459472

460473
if not os.path.exists(correct_maybe_zipped(dag_to_wait.fileloc)):
461-
raise AirflowException(f"The external DAG {self.external_dag_id} was deleted.")
474+
raise ExternalDagDeletedError(f"The external DAG {self.external_dag_id} was deleted.")
462475

463476
if self.external_task_ids:
464477
refreshed_dag_info = DagBag(dag_to_wait.fileloc).get_dag(self.external_dag_id)
478+
if not refreshed_dag_info:
479+
raise ExternalDagNotFoundError(
480+
f"The external DAG {self.external_dag_id} could not be loaded."
481+
)
465482
for external_task_id in self.external_task_ids:
466483
if not refreshed_dag_info.has_task(external_task_id):
467-
raise AirflowException(
484+
raise ExternalTaskNotFoundError(
468485
f"The external task {external_task_id} in DAG {self.external_dag_id} does not exist."
469486
)
470487

471488
if self.external_task_group_id:
472489
refreshed_dag_info = DagBag(dag_to_wait.fileloc).get_dag(self.external_dag_id)
490+
if not refreshed_dag_info:
491+
raise ExternalDagNotFoundError(
492+
f"The external DAG {self.external_dag_id} could not be loaded."
493+
)
473494
if not refreshed_dag_info.has_task_group(self.external_task_group_id):
474-
raise AirflowException(
495+
raise ExternalTaskGroupNotFoundError(
475496
f"The external task group '{self.external_task_group_id}' in "
476497
f"DAG '{self.external_dag_id}' does not exist."
477498
)

providers/standard/src/airflow/providers/standard/triggers/external_task.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,7 @@ async def run(self) -> typing.AsyncIterator[TriggerEvent]:
115115
if failed_count > 0:
116116
yield TriggerEvent({"status": "failed"})
117117
return
118-
else:
119-
yield TriggerEvent({"status": "success"})
120-
return
118+
121119
if self.skipped_states:
122120
skipped_count = await get_count_func(self.skipped_states)
123121
if skipped_count > 0:

0 commit comments

Comments
 (0)