Airflow 当文件不存在时,用于上载文件的DAG失败

Airflow 当文件不存在时,用于上载文件的DAG失败,airflow,directed-acyclic-graphs,Airflow,Directed Acyclic Graphs,我有一个气流DAG,当文件存在时可以完美工作,但当源文件不存在时,错误->会失败 随机地,我从一个给定的源接收文件,我的DAG会收集并处理这些文件。虽然我需要每天运行DAG,但文件不一定每天都在那里。可能是周一,周三,甚至周日晚上 我不担心没有新文件的日子。我担心有几天会有新的文件出现,然后文件会被破坏 我如何告诉DAG,当不存在任何文件时,将顺利退出? 我的DAG如下(请忽略日程设置。我仍处于开发模式): 一种方法是在工作流中添加传感器操作员 尼希尔·贾因: 传感器是一种特殊的气流操纵器,它将

我有一个气流DAG,当文件存在时可以完美工作,但当源文件不存在时,错误->会失败

随机地,我从一个给定的源接收文件,我的DAG会收集并处理这些文件。虽然我需要每天运行DAG,但文件不一定每天都在那里。可能是周一,周三,甚至周日晚上

我不担心没有新文件的日子。我担心有几天会有新的文件出现,然后文件会被破坏

我如何告诉DAG,当不存在任何文件时,将顺利退出? 我的DAG如下(请忽略日程设置。我仍处于开发模式):


一种方法是在工作流中添加传感器操作员

尼希尔·贾因:

传感器是一种特殊的气流操纵器,它将一直运行,直到满足某一标准。例如,您知道一个文件将在某个时间段到达S3存储桶,但文件到达的确切时间不一致

对于您的用例,它看起来像是一个“检查Google云存储中是否存在文件”的操作。您加入传感器的原因是您正在将“确定文件是否存在”操作与“获取文件(并对其进行处理)”操作分离

默认情况下,传感器有两种方法():

  • poke:以
    poke\u间隔
    时间运行的代码,用于测试条件是否正确
  • 执行:使用
    poke
    方法测试由
    poke_间隔
    定义的时间表上的条件;达到
    超时
    参数时失败
在通用文件检测传感器中,操作员收到指令,按照计划检查文件源(例如,每5分钟检查一次,最多3小时,查看文件是否存在)。如果传感器成功满足其测试条件,则传感器将成功并允许DAG继续向下游移动至下一个操作员。如果找不到文件,则超时,传感器操作员被标记为失败

只需一个传感器操作员,您就已经成功地分离了错误案例-当文件不存在时,DAG在
GoogleCloudStorageObjectSensor
而不是
GoogleCloudStorageToBigQueryOperator
失败,当传输逻辑出现问题时,Google CloudStorageToBigQueryOperator会失败。重要的是,对于您的用例,Airflow支持一个
soft\u fail
参数,该参数“将任务标记为失败时跳过”

在下一部分中,我将明确说明我对
GoogleCloudStorage
操作符并不十分熟悉,以此作为下一部分的警告。如果操作员不允许在传感器中进行通配符,您可能需要重新布线传感器的
poke
方法,以便进行更复杂的基于模式的文件检测。这就是Airflow插件体系结构真正发挥作用的地方,它允许您修改和扩展现有的运营商,以满足您的确切需求

我在这里给你举的例子是,
SFTPSensor
只支持在开箱即用的情况下搜索特定的文件。我需要基于通配符的戳,所以我编写了一个插件,修改了
SFTPSensor
,以支持文件标识中的正则表达式。在我的例子中,它只是修改了
poke
,从轮询单个文件的存在切换到轮询文件列表,然后通过正则表达式对列表进行过滤

粗略地看一眼,它看起来像是Google CloudStorageSensor用该方法探测对象的方式。我不知道通配符是否在那里工作,但如果它不工作,看起来有一种方法可以让您实现类似于我为
SFTPRegexSensor
所做的工作流程

我已经包含了SFTPREGEXSERSOR插件的
poke
方法的一些源代码,这些源代码经过了修改,以便在有帮助的情况下与GCS一起工作:

def poke(self, context): 
    # create a hook (removed some of the SSH/SFTP intricacies for simplicity)
    # get list of file(s) matching regex 
    files = hook.list(self.bucket, self.prefix) # you need to define operator paramters for the choices that are dynamic in the operator's poke (e.g. which bucket, what the file prefix is); swapped in the GCS args 
    regex = re.compile(self.remote_filename) 
    files = list(filter(regex.search, files)) 

    if not files: 
        return False 
    return True

您是否考虑过先使用传感器检测文件?我们使用一种模式,首先测试传感器操作员是否存在,然后在数据存在时拉动。我很乐意写一个更详细的答案,但我想先看看你是否排除了这个可能性。没有。我还是个初学者。如果我没有检测到文件,我的问题仍然存在。如何优雅地退出?我该怎么做?谢谢
def poke(self, context): 
    # create a hook (removed some of the SSH/SFTP intricacies for simplicity)
    # get list of file(s) matching regex 
    files = hook.list(self.bucket, self.prefix) # you need to define operator paramters for the choices that are dynamic in the operator's poke (e.g. which bucket, what the file prefix is); swapped in the GCS args 
    regex = re.compile(self.remote_filename) 
    files = list(filter(regex.search, files)) 

    if not files: 
        return False 
    return True