如何避免在某些情况下运行其余的dagster管道

时间:2020-05-26 14:55:33

标签: dagster

说我在达格斯特中有两个固体连接在管道上。第一个实体可能会执行某些处理并生成有效输入,以便其余管道执行,或者生成不应进一步处理的无效输入。为了获得此结果,当数据满足无效条件时,我将引发错误,因此管道将停止,并且将跳过其余实体。

引发错误以解决用例似乎很棘手,有没有办法我可以不使用异常而跳过其余管道的执行?

from dagster import solid, pipeline

@solid
def solid_1(context, x: int):
    y = x + 1

    if y%2 == 0:
        raise "No even number is further processed"

    return y

@solid
def solid_2(context, y:int):
    return y**2

@pipeline
def toy_pipeline():
    solid_2(solid_1())

在这个非常人为的示例中,仅当第一个实体的输出为奇数时才应执行实体2。

在我的实际用例中,第一个实体轮询数据库,有时找不到任何要处理的数据。在这种情况下,不要将执行标记为失败,而应将其标记为成功。可以在每个下游实体中检查数据是否满足条件,但这很快增加了样板。当接收数据的实体找不到要处理的数据时,最好有一种方法跳过所有下游实体的执行。

1 个答案:

答案 0 :(得分:2)

要实现所需的行为,可以使用相应is_required=False上的OutputDefinition参数将输出标记为可选。这意味着固体不必一定要产生产量。

如果没有产生可选的输出,则依赖于该输出的所有下游固体将简单地跳过。这对于使管道短路(这是用例)或更复杂的分支逻辑都很有用。跳过实体时,管道运行不会标记为失败。

您正在使用类型提示定义输入和输出类型,但是由于需要指定is_required参数,因此需要使用显式的OuputDefinition

from dagster import pipeline, solid, RepositoryDefinition, InputDefinition, OutputDefinition, Output
from typing import List

def query_db():
    return []

@solid(output_defs=[OutputDefinition(List[int], 'data', is_required=False)])
def solid_1(context):
    rows = query_db()

    if len(rows) > 0:
        yield Output(rows, output_name="data")


@solid
def solid_2(context, data: List[int]):
    context.log.info(str(data))
    pass


@pipeline
def my_pipeline():
    solid_2(solid_1())

也可以使用solid_2而不是类型提示来定义实体InputDefinition。类型提示是InputDefinitions的语法糖:

@solid(input_defs=[InputDefinition('data', List[int])])
def solid_2(context, data):
    context.log.info(str(data))
    # Process data
    pass

作为旁注:通常,异常是将实体标记为失败的正确方法,并且在Dagster代码中不认为异常。