Tôi đã tìm ra cách tạo quy trình làm việc dựa trên kết quả của các nhiệm vụ trước đó.
Về cơ bản những gì bạn muốn làm là có hai thẻ phụ như sau:
- Xcom đẩy một danh sách (hoặc những gì bạn cần để tạo dòng công việc động sau này) trong thẻ phụ được thực thi trước (xem test1.py
def return_list()
)
- Chuyển đối tượng dag chính làm tham số cho thẻ phụ thứ hai của bạn
- Bây giờ nếu bạn có đối tượng dag chính, bạn có thể sử dụng nó để lấy danh sách các thể hiện nhiệm vụ của nó. Từ danh sách các trường hợp tác vụ đó, bạn có thể lọc ra một tác vụ đang chạy hiện tại bằng cách sử dụng
parent_dag.get_task_instances(settings.Session, start_date=parent_dag.get_active_runs()[-1])[-1]
), người ta có thể thêm nhiều bộ lọc hơn ở đây.
- Với phiên bản tác vụ đó, bạn có thể sử dụng xcom pull để nhận giá trị bạn cần bằng cách chỉ định dag_id cho một trong những thẻ phụ đầu tiên:
dag_id='%s.%s' % (parent_dag_name, 'test1')
- Sử dụng danh sách / giá trị để tạo động tác vụ của bạn
Bây giờ tôi đã thử nghiệm điều này trong cài đặt luồng không khí cục bộ của tôi và nó hoạt động tốt. Tôi không biết liệu phần kéo xcom có gặp vấn đề gì không nếu có nhiều phiên bản dag chạy cùng một lúc, nhưng khi đó có thể bạn sẽ sử dụng một khóa duy nhất hoặc thứ gì đó tương tự để xác định duy nhất xcom giá trị bạn muốn. Người ta có thể tối ưu hóa bước 3. để chắc chắn 100% nhận được một tác vụ cụ thể của dag chính hiện tại, nhưng đối với việc sử dụng của tôi, điều này hoạt động đủ tốt, tôi nghĩ người ta chỉ cần một đối tượng task_instance để sử dụng xcom_pull.
Ngoài ra, tôi làm sạch các xcom cho thẻ phụ đầu tiên trước mỗi lần thực thi, chỉ để đảm bảo rằng tôi không vô tình nhận được bất kỳ giá trị sai nào.
Tôi khá tệ trong việc giải thích, vì vậy tôi hy vọng đoạn mã sau sẽ làm cho mọi thứ rõ ràng:
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
và quy trình làm việc chính:
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