我在气流DAG中有任务。它有三个子任务。不幸的是,有些情况下这个父任务会成功,但三个孩子中的两个会失败(并且对孩子的重试不会修复它们。)
它需要父级重试(即使它没有失败)。
所以我尽职尽责地进入dag run的图表视图并'清除'这个父任务和所有下游任务(+递归)。
有没有办法可以在dag中做到这一点?
答案 0 :(得分:3)
如果您的任务是子标记的一部分,则在Cat
的{{1}}中调用dag.clear()
应该可以解决问题:
on_retry_callback
答案 1 :(得分:2)
我们有一个类似的问题,我们通过将要重复的依赖项放入一个子dag中解决了。然后,当子dag重试时,我们使用on_retry_callback
清除子dag任务状态,以使它们再次运行。
sub_dag = SubDagOperator(
retry_delay=timedelta(seconds=30),
subdag=create_sub_dag(),
on_retry_callback=callback_subdag_clear,
task_id=sub_dag_name,
dag=dag,
)
def callback_subdag_clear(context):
"""Clears a sub-dag's tasks on retry."""
dag_id = "{}.{}".format(
context['dag'].dag_id,
context['ti'].task_id,
)
execution_date = context['execution_date']
sub_dag = DagBag().get_dag(dag_id)
sub_dag.clear(
start_date=execution_date,
end_date=execution_date,
only_failed=False,
only_running=False,
confirm_prompt=False,
include_subdags=False
)
(最初从这里https://gist.github.com/nathairtras/6ce0b0294be8c27d672e2ad52e8f2117取得)
答案 2 :(得分:0)
它没有直接回答您的问题,但我可以建议更好的解决方法:
default_args = {
'start_date': datetime(2017, 12, 16),
'depends_on_past': True,
}
dag = DAG(
dag_id='main_dag',
schedule_interval='@daily',
default_args=default_args,
max_active_runs=1,
retries=100,
retry_delay= timedelta(seconds=120)
)
在DAG中将depends_on_past
设置为True。
然后在这个dag的任务中,使用重试限制重试次数
DummyOperator(
task_id='bar',
retries=0
dag=child)
这样,当任何任务失败时,DAG会被标记为失败。然后重试DAG。
答案 3 :(得分:0)
我们选择使用clear_task_instances
的{{1}}方法:
taskinstance
您需要提供要在回调中清除的任务列表,例如,在任何子任务上:
@provide_session
def clear_tasks_fn(tis,session=None,activate_dag_runs=False,dag=None) -> None:
"""
Wrapper for `clear_task_instances` to be used in callback function
(that accepts only `context`)
"""
taskinstance.clear_task_instances(tis=tis,
session=session,
activate_dag_runs=activate_dag_runs,
dag=dag)
def clear_tasks_callback(context) -> None:
"""
Clears tasks based on list passed as `task_ids_to_clear` parameter
To be used as `on_retry_callback`
"""
all_tasks = context["dag_run"].get_task_instances()
dag = context["dag"]
task_ids_to_clear = context["params"].get("task_ids_to_clear", [])
tasks_to_clear = [ ti for ti in all_tasks if ti.task_id in task_ids_to_clear ]
clear_tasks_fn(tasks_to_clear,
dag=dag)