Önceki görevlerin sonucuna göre iş akışları oluşturmanın bir yolunu buldum.
Temel olarak yapmak istediğiniz şey, aşağıdakileri içeren iki alt etikete sahip olmaktır:
- Xcom, ilk çalıştırılan alt etiket içinde bir liste (veya daha sonra dinamik iş akışını oluşturmak için ihtiyacınız olan her şeyi) itin (bkz. Test1.py
def return_list()
)
- Ana dag nesnesini parametre olarak ikinci alt etiketinize iletin
- Şimdi ana dag nesnesine sahipseniz, onu görev örneklerinin bir listesini almak için kullanabilirsiniz. Bu görev örnekleri listesinden, geçerli çalıştırmanın bir görevini
parent_dag.get_task_instances(settings.Session, start_date=parent_dag.get_active_runs()[-1])[-1]
) kullanarak filtreleyebilirsiniz, muhtemelen buraya daha fazla filtre eklenebilir.
- Bu görev örneğiyle, ilk alt etiketten birine dag_id belirterek ihtiyacınız olan değeri elde etmek için xcom pull kullanabilirsiniz:
dag_id='%s.%s' % (parent_dag_name, 'test1')
- Görevlerinizi dinamik olarak oluşturmak için listeyi / değeri kullanın
Şimdi bunu yerel hava akımı tesisatımda test ettim ve iyi çalışıyor. Aynı anda çalışan birden fazla dag örneği varsa xcom çekme kısmında herhangi bir sorun olup olmayacağını bilmiyorum, ancak o zaman xcom'u benzersiz bir şekilde tanımlamak için muhtemelen benzersiz bir anahtar veya buna benzer bir şey kullanırsınız. istediğiniz değer. Muhtemelen 3. adımı, mevcut ana dag'in belirli bir görevini alacağınızdan% 100 emin olacak şekilde optimize edebilir, ancak benim kullanımım için bu yeterince iyi performans gösteriyor, bence xcom_pull'u kullanmak için yalnızca bir task_instance nesnesine ihtiyaç var.
Ayrıca, kazara yanlış bir değer almadığımdan emin olmak için, her yürütmeden önce ilk alt etiket için xcom'ları temizliyorum.
Açıklamakta oldukça kötüyüm, bu yüzden aşağıdaki kodun her şeyi netleştireceğini umuyorum:
test1.py
from airflow.models import DAG
import logging
from airflow.operators.python_operator import PythonOperator
from airflow.operators.postgres_operator import PostgresOperator
log = logging.getLogger(__name__)
def test1(parent_dag_name, start_date, schedule_interval):
dag = DAG(
'%s.test1' % parent_dag_name,
schedule_interval=schedule_interval,
start_date=start_date,
)
def return_list():
return ['test1', 'test2']
list_extract_folder = PythonOperator(
task_id='list',
dag=dag,
python_callable=return_list
)
clean_xcoms = PostgresOperator(
task_id='clean_xcoms',
postgres_conn_id='airflow_db',
sql="delete from xcom where dag_id='{{ dag.dag_id }}'",
dag=dag)
clean_xcoms >> list_extract_folder
return dag
test2.py
from airflow.models import DAG, settings
import logging
from airflow.operators.dummy_operator import DummyOperator
log = logging.getLogger(__name__)
def test2(parent_dag_name, start_date, schedule_interval, parent_dag=None):
dag = DAG(
'%s.test2' % parent_dag_name,
schedule_interval=schedule_interval,
start_date=start_date
)
if len(parent_dag.get_active_runs()) > 0:
test_list = parent_dag.get_task_instances(settings.Session, start_date=parent_dag.get_active_runs()[-1])[-1].xcom_pull(
dag_id='%s.%s' % (parent_dag_name, 'test1'),
task_ids='list')
if test_list:
for i in test_list:
test = DummyOperator(
task_id=i,
dag=dag
)
return dag
ve ana iş akışı:
test.py
from datetime import datetime
from airflow import DAG
from airflow.operators.subdag_operator import SubDagOperator
from subdags.test1 import test1
from subdags.test2 import test2
DAG_NAME = 'test-dag'
dag = DAG(DAG_NAME,
description='Test workflow',
catchup=False,
schedule_interval='0 0 * * *',
start_date=datetime(2018, 8, 24))
test1 = SubDagOperator(
subdag=test1(DAG_NAME,
dag.start_date,
dag.schedule_interval),
task_id='test1',
dag=dag
)
test2 = SubDagOperator(
subdag=test2(DAG_NAME,
dag.start_date,
dag.schedule_interval,
parent_dag=dag),
task_id='test2',
dag=dag
)
test1 >> test2