Skip to content

Commit e1b5af4

Browse files
fix: Correct XPK DAG final status reporting issue (GoogleCloudPlatform#1304)
Correct DAG Status Reporting via Airflow Setup/Teardown API __The Problem:__ By default, Airflow evaluates the final DAG run status based on the success of its leaf nodes. In our workload runs, `clean_up_workload` acts as a leaf node that is typically triggered with `all_done` rules. When a training workload failed, the cleanup task still completed successfully, causing the Airflow DAG to be incorrectly reported as SUCCESS. __The Solution:__ We transitioned the cleanup logic to use Airflow's Setup/Teardown API: Marked `clean_up_workload` as a teardown task linked to `launch_workload` via `.as_teardown(setups=launch_workload)`. This ensures that successful cleanup runs do not mask upstream failures (the DAG run status will now be determined by the actual work task, `wait_for_workload_completion`). Configured `on_failure_fail_dagrun=True` inside `as_teardown(...)`. This ensures that if the cleanup task itself fails (e.g., if we fail to delete GKE resources, risking resource leaks), the DAG run will be flagged as FAILED.
1 parent baf9f2d commit e1b5af4

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

xlml/apis/task.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ def run(
227227
A task group with the following task : run_model.
228228
"""
229229
with TaskGroup(group_id=self.test_cfg.benchmark_id) as group:
230+
dummy_op_for_teardown = EmptyOperator(
231+
task_id="dummy_op_for_teardown"
232+
).as_setup()
233+
230234
update_image_tag_cmd = axlearn.update_image_tag_cmd.override(
231235
owner=self.test_cfg.task_owner
232236
)(
@@ -293,6 +297,8 @@ def run(
293297
zone=self.gcp_cfg.zone,
294298
cluster_name=self.test_cfg.cluster_name,
295299
xpk_branch=xpk.MAIN_BRANCH,
300+
).as_teardown(
301+
setups=dummy_op_for_teardown, on_failure_fail_dagrun=True
296302
)
297303

298304
# flow1: The launcher task (Kubernetes Pod) that runs the workload.
@@ -302,7 +308,12 @@ def run(
302308
flow1 = run_workload
303309
flow2 = wait_for_workload_start >> wait_for_workload_completion >> cleanup
304310

305-
_ = update_image_tag_cmd >> gen_cmds >> [flow1, flow2]
311+
_ = (
312+
update_image_tag_cmd
313+
>> gen_cmds
314+
>> dummy_op_for_teardown
315+
>> [flow1, flow2]
316+
)
306317

307318
return group
308319

@@ -471,6 +482,10 @@ def run_model_with_node_interruption(
471482
self.task_test_config.benchmark_id,
472483
)
473484

485+
dummy_op_for_teardown = EmptyOperator(
486+
task_id="dummy_op_for_teardown"
487+
).as_setup()
488+
474489
launch_workload_and_wait_for_reach_step = (
475490
self.launch_workload_with_node_reach_to_step(
476491
workload_id,
@@ -512,10 +527,11 @@ def run_model_with_node_interruption(
512527
zone=self.task_gcp_config.zone,
513528
cluster_name=self.task_test_config.cluster_name,
514529
xpk_branch=xpk_branch,
515-
)
530+
).as_teardown(setups=dummy_op_for_teardown, on_failure_fail_dagrun=True)
516531

517532
_ = (
518533
(workload_id, gcs_path)
534+
>> dummy_op_for_teardown
519535
>> launch_workload_and_wait_for_reach_step
520536
>> run_node_interruption
521537
>> wait_for_workload_completion
@@ -731,6 +747,11 @@ def run_model(
731747
self.task_test_config.gcs_subfolder,
732748
self.task_test_config.benchmark_id,
733749
)
750+
751+
dummy_op_for_teardown = EmptyOperator(
752+
task_id="dummy_op_for_teardown"
753+
).as_setup()
754+
734755
launch_workload = self.launch_workload(
735756
workload_id,
736757
gcs_path,
@@ -756,10 +777,11 @@ def run_model(
756777
zone=self.task_gcp_config.zone,
757778
cluster_name=self.task_test_config.cluster_name,
758779
xpk_branch=xpk_branch,
759-
)
780+
).as_teardown(setups=dummy_op_for_teardown, on_failure_fail_dagrun=True)
760781

761782
_ = (
762783
(workload_id, gcs_path)
784+
>> dummy_op_for_teardown
763785
>> launch_workload
764786
>> wait_for_workload_completion
765787
>> clean_up_workload

0 commit comments

Comments
 (0)