簡體   English   中英

Airflow 2 中的 S3KeySensor

[英]S3KeySensor in Airflow 2

我有一個名為my_dag.py的 dag,它利用 Airflow 2 中的 S3KeySensor 來檢查是否存在 s3 密鑰。 當我直接在 dag 內部使用傳感器時,它起作用了:

with TaskGroup('check_exists') as check_exists: 
    
  path = 's3://my-bucket/data/my_file'
  poke_interval = 30
  timeout = 60*60
  mode = 'reschedule'
  dependency_name = 'my_file'

  S3KeySensor(
    task_id = 'check_' + dependency_name + '_exists',
    bucket_key = path,
    poke_interval = poke_interval,
    timeout = timeout,
    mode = mode
  )

上面的日志看起來像:

[2022-05-03, 19:51:26 UTC] {s3.py:105} INFO - Poking for key : s3://my-bucket/data/my_file
[2022-05-03, 19:51:26 UTC] {base_aws.py:90} INFO - Retrieving region_name from Connection.extra_config['region_name']
[2022-05-03, 19:51:27 UTC] {taskinstance.py:1701} INFO - Rescheduling task, marking task as UP_FOR_RESCHEDULE

這是對的。 預計會重新安排,因為該文件尚不存在。

但是,我想檢查其他 dag 中的任意數量的路徑,因此我將傳感器移動到另一個名為 helpers.py 的文件中名為testhelpers.py中。 我在調用test的任務組中的my_dag.py中使用 python 運算符。 它看起來像這樣:

with TaskGroup('check_exists') as check_exists:

  path = 's3://my-bucket/data/my_file'
  dependency_name = 'my_file'

  wait_for_dependencies = PythonOperator(
    task_id = 'wait_for_my_file',
    python_callable = test,
    op_kwargs = {
      'dependency_name': dependency_name,
      'path': path
    },
    dag = dag
  )

  wait_for_dependencies

helpers.py 中的helpers.py test如下所示:

def test(dependency_name, path, poke_interval = 30, timeout = 60 * 60, mode = 'reschedule'):

    S3KeySensor(
        task_id = 'check_' + dependency_name + '_exists',
        bucket_key = path,
        poke_interval = poke_interval,
        timeout = timeout,
        mode = mode
    )

但是,當我運行 dag 時,即使該文件不存在,該步驟也被標記為成功。 日志顯示:

[2022-05-03, 20:07:54 UTC] {python.py:175} INFO - Done. Returned value was: None
[2022-05-03, 20:07:54 UTC] {taskinstance.py:1282} INFO - Marking task as SUCCESS.

似乎 airflow 不喜歡通過 python 操作員使用傳感器。 這是真的? 還是我做錯了什么?

我的目標是遍歷多條路徑並檢查每條路徑是否存在。 但是,我在其他 dag 中這樣做,這就是為什么我將傳感器放在另一個文件中的 function 中。

如果有其他想法可以做到這一點,我很開放!

謝謝你的幫助!

這不會像您預期的那樣工作。 您創建了一個運算符內部運算符的案例。 有關這意味着什么的信息,請參閱此答案

在您的情況下,您使用PythonOperator S3KeySensor 這意味着當PythonOperator運行時,它只執行 S3KeySensor 的 init S3KeySensor - 它不會調用運算符本身的邏輯。 在運算符內部使用運算符是一種不好的做法。

當您嘗試在操作員內部使用傳感器時,您的情況更加極端。 傳感器需要為每個戳周期調用poke() function。 為簡化起見 - 當您像設置它們時那樣設置mode = 'reschedule'時,您無法享受 Sensor 的強大功能,因為 reschedule 意味着如果條件尚未滿足,您想要釋放工作人員,但PythonOperator不知道該怎么做.

如何解決您的問題:

選項1:

從您展示的代碼中,您可以簡單地執行以下操作:

with TaskGroup('check_exists') as check_exists:
    
  path = 's3://my-bucket/data/my_file'
  dependency_name = 'my_file'

  S3KeySensor(
    task_id='check_' + dependency_name + '_exists',
    bucket_key=path,
    poke_interval=30,
    timeout=60 * 60,
    mode='reschedule'
  )

我沒有看到為什么這對你不起作用的原因。

選項 2:

如果由於某種原因選項 1 對您不利,則創建一個自定義傳感器,該傳感器也接受dependency_namepath ,並像任何其他運算符一樣使用它。 我沒有測試它,但像下面這樣的東西應該可以工作:

class MyS3KeySensor(S3KeySensor):
    def __init__(
        self,
        *,
        dependency_name:str = None,
        path: str = None,
        **kwargs,
    ):
        super().__init__(**kwargs)
        self.task_id = task_id = 'check_' + dependency_name + '_exists'
        self.bucket_name = path

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM