有没有一种方法可以(一次)回填历史数据以用于新的Prefect?

时间:2020-09-23 13:58:06

标签: airflow etl prefect

我刚刚开始阅读有关Prefect的内容(并且对Airflow有所了解)。

我的目标是设置一个任务,该任务每天在Prefect中运行,并将数据收集到一个文件夹中(我想这正是Prefect可以帮助我做的事情)。 另外,我的目标是填充历史数据(就像我及时地执行了这项工作一样。)

在Airflow中,有一个start_date的概念,在过去设置时,DAG将从该日期开始运行,并在每个间隔中填充。

例如,如果我有一个任务需要一个日期并返回该日期的数据,例如:

# Pseudo code
def get_values_from_somewhere(date: datetime) -> dict:
    return fetched_values_in_json(date)

在Prefect中是否有本地方法可以做到这一点? 尽管在here中提到了回填,但我在这里或文档的任何地方都找不到答案。 任何帮助/指导都将非常有用。

我尝试过的事情:

当我将schedule设置为:

from datetime import datetime, timedelta

from prefect.schedules import Schedule

schedule = Schedule(clocks=[IntervalClock(interval=timedelta(hours=24), start_date=datetime(2019, 1, 1))])

然后我做flow.run(),我得到:

INFO:prefect.My-Task:Waiting for next scheduled run at 2020-09-24T00:00:00+00:00

我期望的是从提供的start_date开始运行,然后暂停直到到达当前时间,然后等待下一个时间表。

1 个答案:

答案 0 :(得分:4)

Prefect不会对Flow或其任务如何依赖时间做出任何隐式假设,因此执行回填取决于Flow的结构。时间显式影响流的方式通常有两种:

  • 通过ParameterDateTimeParameter
  • 通过prefect.context(包括许多与时间相关的字段,在here中进行了描述)

鉴于执行回填可以通过创建任意数量的临时计划流运行并覆盖适当的上下文关键字或默认参数值来实现。 (请注意,可以为任何流创建临时运行,而不管该流是否具有时间表。)

为更加精确,下面是两个示例,这些示例触发一次回填运行(以容纳更多运行,循环遍历适当的值并为每个运行创建一个运行):

使用上下文

import pendulum
import prefect


@prefect.task
def do_something_time_specific():
    """
    This task uses the timestamp provided to the custom `backfill_time`
    context key; if that does not exist, it falls back on the built-in
    `scheduled_start_time` context key.
    """

    current_time = prefect.context.get("backfill_time") or prefect.context.get("scheduled_start_time")
    if isinstance(current_time, str):
        current_time = pendulum.parse(current_time)
    # performs some action dealing with this timestamp


flow = Flow("backfill", tasks=[do_something_time_specific])

## using Core
flow.run() # will use current timestamp
flow.run(context={"backfill_start_time": "1986-01-02"}) # will use old timestamp

## using an API
prefect.Client().create_flow_run(flow_id="FLOWID", 
    context={"backfill_start_time": "1986-01-02"}) # will use old timestamp

使用参数

import pendulum
import prefect


current_time = prefect.Parameter("current_time", default=None)

@prefect.task
def do_something_time_specific(current_time):
    """
    This task uses the timestamp provided to the task explicitly.
    """
    current_time = current_time or pendulum.now("utc") # uses "now" if not provided
    if isinstance(current_time, str):
        current_time = pendulum.parse(current_time)

    # performs some action dealing with this timestamp


with Flow("backfill") as flow:
    do_something_time_specific(current_time)


## using Core
flow.run() # will use current timestamp
flow.run(current_time="1986-01-02") # will use old timestamp

## using an API
prefect.Client().create_flow_run(flow_id="FLOWID", 
    parameters={"current_time": "1986-01-02"}) # will use old timestamp

较新的参数类,例如DateTimeParameter提供了更好的键入保证,但是希望这可以证明这一想法。

编辑:为完整起见,请注意,可以通过运行flow.run(run_on_schedule=False)

在Core中为具有计划的流创建临时运行