Triggers 气流触发器RunOperator如何更改执行日期

Triggers 气流触发器RunOperator如何更改执行日期,triggers,airflow,Triggers,Airflow,我注意到,对于计划任务,执行日期是根据 气流是为满足ETL需求而开发的一种解决方案。在ETL世界中, 您通常会汇总数据。所以,如果我想总结一下 2016-02-19,我会在2016-02-20格林威治标准时间午夜做这件事 2016年2月19日的所有数据可用后 但是,当一个dag触发另一个dag时,执行时间设置为now() 是否有办法使触发的dag与触发dag的执行时间相同?当然,我可以重写模板并使用Dayed\ds,但是,这是一个棘手的解决方案。下面的类扩展了TriggerDagRunOpera

我注意到,对于计划任务,执行日期是根据

气流是为满足ETL需求而开发的一种解决方案。在ETL世界中, 您通常会汇总数据。所以,如果我想总结一下 2016-02-19,我会在2016-02-20格林威治标准时间午夜做这件事 2016年2月19日的所有数据可用后

但是,当一个dag触发另一个dag时,执行时间设置为now()


是否有办法使触发的dag与触发dag的执行时间相同?当然,我可以重写模板并使用Dayed\ds,但是,这是一个棘手的解决方案。

下面的类扩展了
TriggerDagRunOperator
,允许将执行日期作为字符串传递,然后将其转换回日期时间。这有点粗糙,但这是我找到的完成工作的唯一方法

从日期时间导入日期时间
导入日志记录
从气流导入设置
从airflow.utils.state导入状态
从airflow.models导入DagBag
从airflow.operators.dagrun\运算符导入触发器DagRunOperator,DagRunOrder
MMTTriggerDagRunOperator类(TriggerDagRunOperator类):
"""
已修补MMT以传递显式执行日期
(否则很难钩住datetime.now()date)。
要明确设置目标DAG上的执行日期时使用
从控制器DAG。
改编自Paul Elliot关于邮件列表归档的解决方案:
http://mail-archives.apache.org/mod_mbox/airflow-dev/201711.mbox/%3cCAJuWvXgLfipPmMhkbf63puPGfi_ezj8vHYWoSHpBXysXhF_oZQ@mail.gmail.com%3e
参数
------------------
执行日期:str
自定义执行日期(jinja'd)
用法示例:
-------------------
my_dag_trigger_operator=MMTTriggerDagRunOperator(
执行日期=“{execution\u date}”
任务\u id='my\u dag\u trigger\u operator',
触发器_dag_id='my_target_dag_id',
python_callable=lambda:random.getrandbits(1),
params={},
dag=我的控制器
)
"""
模板\字段=('execution\ u date',)
定义初始化__(
self、trigger\u dag\u id、python\u可调用、执行日期、,
*args,**kwargs
):
self.execution\u date=执行日期
超级(MMTTriggerDagRunOperator,self)。\uu init__(
trigger\u dag\u id=trigger\u dag\u id,python\u callable=python\u callable,
*args,**kwargs
)
def执行(自身、上下文):
run_id_dt=datetime.strtime(self.execution_date,“%Y-%m-%d%H:%m:%S”)
dro=DagRunOrder(run\u id='trig\u'+run\u id\u dt.isoformat())
dro=self.python\u可调用(上下文,dro)
如果是dro:
session=settings.session()
dbag=DagBag(settings.DAGS\u文件夹)
trigger\u dag=dbag.get\u dag(self.trigger\u dag\u id)
dr=触发\u dag.create\u dag运行(
run\u id=dro.run\u id,
state=state.RUNNING,
执行日期=自执行日期,
conf=dro.payload,
外部(触发器=真)
logging.info(“创建DagRun{}.format(dr))
会话.添加(dr)
session.commit()
session.close()
其他:
logging.info(“未满足标准,继续”)
使用此选项而不设置
execution\u date=now()
时,可能会遇到一个问题:如果您尝试使用相同的
execution\u date启动dag两次,操作员将抛出mysql错误。这是因为
execution\u date
dag\u id
用于创建行索引,不能插入索引相同的行


我想不出有什么理由让你想在生产环境中运行两个相同的DAG,并且执行日期相同,但这是我在测试时遇到的问题,你不应该对此感到惊慌。只需清除旧作业或使用不同的日期时间。

我对mmttriggerdagruno运算符做了一些改进。该功能检查dag_运行是否已经存在,如果找到,请使用气流清除功能重新启动dag。这允许我们在dag之间创建一个依赖关系,因为将执行日期移动到触发的dag的可能性打开了一个惊人的可能性宇宙。我想知道为什么这不是气流中的默认行为

   def execute(self, context):
        run_id_dt = datetime.strptime(self.execution_date, '%Y-%m-%d %H:%M:%S')
        dro = DagRunOrder(run_id='trig__' + run_id_dt.isoformat())
        dro = self.python_callable(context, dro)
        if dro:
            session = settings.Session()
            dbag = DagBag(settings.DAGS_FOLDER)
            trigger_dag = dbag.get_dag(self.trigger_dag_id)

            if not trigger_dag.get_dagrun( self.execution_date ):
                dr = trigger_dag.create_dagrun(
                       run_id=dro.run_id,
                       state=State.RUNNING,
                       execution_date=self.execution_date,
                       conf=dro.payload,
                       external_trigger=True
                )
                logging.info("Creating DagRun {}".format(dr))
                session.add(dr)
                session.commit()
            else:
                trigger_dag.clear( 
                    start_date = self.execution_date,
                    end_date = self.execution_date,
                    only_failed = False,
                    only_running = False,
                    confirm_prompt = False, 
                    reset_dag_runs = True, 
                    include_subdags= False,
                    dry_run = False 
                )
                logging.info("Cleared DagRun {}".format(trigger_dag))

            session.close()
        else:
            logging.info("Criteria not met, moving on")

“气流”的“实验API”部分提供了一个函数,可用于触发具有特定执行日期的dag

您可以将此函数作为PythonOperator的一部分调用,并实现此目标

所以它看起来像
来自afflow.api.common.experimental.trigger\u dag导入trigger\u dag

trigger_operator=PythonOperator(task_id='YOUR_TASK_ID',
                                python_callable=trigger_dag,
                                op_args=['dag_id'],
                                op_kwargs={'execution_date': datetime.now()})

TriggerDagRunOperator
现在有一个
execution\u date
参数来设置触发运行的执行日期。 很遗憾,该参数不在模板字段中。 如果将其添加到模板字段中(或者如果覆盖运算符并更改模板字段值),则可以如下使用:

my_trigger_task= TriggerDagRunOperator(task_id='my_trigger_task',
                                              trigger_dag_id="triggered_dag_id",
                                              python_callable=conditionally_trigger,
                                              execution_date= '{{execution_date}}',
                                              dag=dag)
它尚未发布,但您可以在此处看到来源:

进行更改的提交是:

这是一个很好的解决方案,远不是最好的解决方案,它仍然有帮助(很多)。当前(v1.9.0)气流的索引为(dag\u id,run\u id)。。。您对早期版本的airflow的sql错误有何评论?我运行的是v1.8.0,因此您可能会认为这在1.9+中不是问题,我运行的是airflow 1.9.0,我有相同的错误
sqlalchemy.exc.IntegrityError:(psycopg2.IntegrityError)重复的键值违反唯一约束“dag\u run\u dag\u id\u execution\u date\u key
键(dag\u id,execution\u date)已存在。