फ़ाइल नाम की सरणी के आधार पर मूल डैग से गतिशील सबडैग बनाने की कोशिश कर रहा है


10

मैं s3 फ़ाइलों को एक "नॉन-डिलीटिंग" बकेट से स्थानांतरित करने का प्रयास कर रहा हूं (जिसका अर्थ है कि मैं फ़ाइलों को हटा नहीं सकता) एयरफ्लो का उपयोग करके जीसीएस के लिए। मुझे इस बात की गारंटी नहीं दी जा सकती कि नई फाइलें हर रोज होंगी, लेकिन मुझे हर रोज नई फाइलों की जांच करनी चाहिए।

मेरी समस्या सबडैग्स की गतिशील रचना है। यदि फाइलें हैं, तो मुझे सबडैग्स की जरूरत है। यदि फाइलें नहीं हैं, तो मुझे सबडैग्स की जरूरत नहीं है। मेरी समस्या अपस्ट्रीम / डाउनस्ट्रीम सेटिंग्स है। मेरे कोड में, यह फ़ाइलों का पता लगाता है, लेकिन सबडैग्स को बंद नहीं करता है क्योंकि वे माना जाता है। मुझे कुछ याद आ रहा है।

यहाँ मेरा कोड है:

from airflow import models
from  airflow.utils.helpers import chain
from airflow.providers.amazon.aws.hooks.s3 import S3Hook
from airflow.operators.python_operator import PythonOperator, BranchPythonOperator
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators.subdag_operator import SubDagOperator
from airflow.contrib.operators.s3_to_gcs_operator import S3ToGoogleCloudStorageOperator
from airflow.utils import dates
from airflow.models import Variable
import logging

args = {
    'owner': 'Airflow',
    'start_date': dates.days_ago(1),
    'email': ['sinistersparrow1701@gmail.com'],
    'email_on_failure': True,
    'email_on_success': True,
}

bucket = 'mybucket'
prefix = 'myprefix/'
LastBDEXDate = int(Variable.get("last_publish_date"))
maxdate = LastBDEXDate
files = []

parent_dag = models.DAG(
    dag_id='My_Ingestion',
    default_args=args,
    schedule_interval='@daily',
    catchup=False
)

def Check_For_Files(**kwargs):
    s3 = S3Hook(aws_conn_id='S3_BOX')
    s3.get_conn()
    bucket = bucket
    LastBDEXDate = int(Variable.get("last_publish_date"))
    maxdate = LastBDEXDate
    files = s3.list_keys(bucket_name=bucket, prefix='myprefix/file')
    for file in files:
        print(file)
        print(file.split("_")[-2])
        print(file.split("_")[-2][-8:])  ##proves I can see a date in the file name is ok.
        maxdate = maxdate if maxdate > int(file.split("_")[-2][-8:]) else int(file.split("_")[-2][-8:])
    if maxdate > LastBDEXDate:
        return 'Start_Process'
    return 'finished'

def create_subdag(dag_parent, dag_id_child_prefix, file_name):
    # dag params
    dag_id_child = '%s.%s' % (dag_parent.dag_id, dag_id_child_prefix)

    # dag
    subdag = models.DAG(dag_id=dag_id_child,
              default_args=args,
              schedule_interval=None)

    # operators
    s3_to_gcs_op = S3ToGoogleCloudStorageOperator(
        task_id=dag_id_child,
        bucket=bucket,
        prefix=file_name,
        dest_gcs_conn_id='GCP_Account',
        dest_gcs='gs://my_files/To_Process/',
        replace=False,
        gzip=True,
        dag=subdag)


    return subdag

def create_subdag_operator(dag_parent, filename, index):
    tid_subdag = 'file_{}'.format(index)
    subdag = create_subdag(dag_parent, tid_subdag, filename)
    sd_op = SubDagOperator(task_id=tid_subdag, dag=dag_parent, subdag=subdag)
    return sd_op

def create_subdag_operators(dag_parent, file_list):
    subdags = [create_subdag_operator(dag_parent, file, file_list.index(file)) for file in file_list]
    # chain subdag-operators together
    chain(*subdags)
    return subdags

check_for_files = BranchPythonOperator(
    task_id='Check_for_s3_Files',
    provide_context=True,
    python_callable=Check_For_Files,
    dag=parent_dag
)

finished = DummyOperator(
    task_id='finished',
    dag=parent_dag
)

decision_to_continue = DummyOperator(
    task_id='Start_Process',
    dag=parent_dag
)

if len(files) > 0:
    subdag_ops = create_subdag_operators(parent_dag, files)
    check_for_files >> decision_to_continue >> subdag_ops[0] >> subdag_ops[-1] >> finished


check_for_files >> finished

इन DAGS के बैकएंड पर किस तरह की नौकरी चलती है, ये sparkजॉब या कोई pythonस्क्रिप्ट है और आप इसे चलाने के लिए क्या उपयोग कर रहे हैं जैसे livyया कोई अन्य विधि
ashwin agrawal

मुझे क्षमा करें, मुझे यह प्रश्न समझ में नहीं आया। क्या आप कृपया आराम कर सकते हैं?
arcee123

मेरा मतलब है कि आप केवल सरल अजगर लिपियों का उपयोग कर रहे हैं और किसी भी स्पार्क नौकरी का सही उपयोग नहीं कर रहे हैं?
अश्विन अग्रवाल

हाँ। सरल ऑपरेटर जो एयरफ्लो में डिफ़ॉल्ट हैं। मैं S3 में ध्वजांकित फ़ाइलों के आधार पर एक गतिशील दर पर मौजूदा ऑपरेटरों को जोड़ना चाहता हूं जिसे मैं GCS में निगलना चाहता हूं।
arcee123

filesखाली सूची क्यों है ?
ओलुवाफेमी सुले

जवाबों:


3

नीचे एयरफ्लो में एक गतिशील डीएजी या उप-डीएजी बनाने का अनुशंसित तरीका है, हालांकि अन्य तरीके भी हैं, लेकिन मुझे लगता है कि यह काफी हद तक आपकी समस्या पर लागू होगा।

सबसे पहले, एक फ़ाइल बनाएं (yaml/csv)जिसमें सभी s3फ़ाइलों और स्थानों की सूची शामिल है , आपके मामले में आपने उन्हें सूची में संग्रहीत करने के लिए एक फ़ंक्शन लिखा है, मैं कहूंगा कि उन्हें एक अलग yamlफ़ाइल में संग्रहीत करें और इसे एयरफ़्लो एनवी में रन समय पर लोड करें और फिर बनाएं DAGs।

नीचे एक नमूना yamlफ़ाइल है: dynamicDagConfigFile.yaml

job: dynamic-dag
bucket_name: 'bucket-name'
prefix: 'bucket-prefix'
S3Files:
    - File1: 'S3Loc1'
    - File2: 'S3Loc2'
    - File3: 'S3Loc3'

आप Check_For_Filesउन्हें yamlफ़ाइल में संग्रहीत करने के लिए अपने फ़ंक्शन को संशोधित कर सकते हैं ।

अब हम गतिशील डेग निर्माण पर आगे बढ़ सकते हैं:

पहले डमी ऑपरेटरों का उपयोग करके दो कार्यों को परिभाषित करें, iethe प्रारंभ और अंतिम कार्य। ऐसे कार्य वे हैं जिनके बीच हम DAGगतिशील रूप से उनके बीच कार्य करके निर्माण करने जा रहे हैं:

start = DummyOperator(
    task_id='start',
    dag=dag
)

end = DummyOperator(
    task_id='end',
    dag=dag)

डायनेमिक डीएजी: हम PythonOperatorsएयरफ्लो में उपयोग करेंगे । फ़ंक्शन को कार्य आईडी के रूप में तर्क प्राप्त करना चाहिए; एक अजगर समारोह निष्पादित किया जा सकता है, यानी, अजगर संचालक के लिए अजगर; और निष्पादन के दौरान इस्तेमाल किए जाने वाले आर्ग का एक सेट।

एक तर्क शामिल करें task id। इसलिए, हम गतिशील तरीके से उत्पन्न कार्यों के बीच डेटा का आदान-प्रदान कर सकते हैं, जैसे, के माध्यम से XCOM

आप इस डायनेमिक डेग के भीतर अपने ऑपरेशन फ़ंक्शन को निर्दिष्ट कर सकते हैं s3_to_gcs_op

def createDynamicDAG(task_id, callableFunction, args):
    task = PythonOperator(
        task_id = task_id,
        provide_context=True,
        #Eval is used since the callableFunction var is of type string
        #while the python_callable argument for PythonOperators only receives objects of type callable not strings.
        python_callable = eval(callableFunction),
        op_kwargs = args,
        xcom_push = True,
        dag = dag,
    )
    return task

अंत में yaml फ़ाइल में मौजूद स्थान के आधार पर आप डायनामिक डैग्स बना सकते हैं, पहले पढ़ें yaml फाइल को नीचे की तरह और डायनेमिक डैग बनाएं:

with open('/usr/local/airflow/dags/config_files/dynamicDagConfigFile.yaml') as f:
    # use safe_load instead to load the YAML file
    configFile = yaml.safe_load(f)

    #Extract file list
    S3Files = configFile['S3Files']

    #In this loop tasks are created for each table defined in the YAML file
    for S3File in S3Files:
        for S3File, fieldName in S3File.items():

            #Remember task id is provided in order to exchange data among tasks generated in dynamic way.
            get_s3_files = createDynamicDAG('{}-getS3Data'.format(S3File), 
                                            'getS3Data', 
                                            {}) #your configs here.

            #Second step is upload S3 to GCS
            upload_s3_toGCS = createDynamicDAG('{}-uploadDataS3ToGCS'.format(S3File), 'uploadDataS3ToGCS', {'previous_task_id':'{}-'})

#write your configs again here like S3 bucket name prefix extra or read from yaml file, and other GCS config.

अंतिम DAG परिभाषा:

विचार यह है कि

#once tasks are generated they should linked with the
#dummy operators generated in the start and end tasks. 
start >> get_s3_files
get_s3_files >> upload_s3_toGCS
upload_s3_toGCS >> end

पूर्ण एयरफ़्लो कोड क्रम में:

import yaml
import airflow
from airflow import DAG
from datetime import datetime, timedelta, time
from airflow.operators.python_operator import PythonOperator
from airflow.operators.dummy_operator import DummyOperator

start = DummyOperator(
    task_id='start',
    dag=dag
)


def createDynamicDAG(task_id, callableFunction, args):
    task = PythonOperator(
        task_id = task_id,
        provide_context=True,
        #Eval is used since the callableFunction var is of type string
        #while the python_callable argument for PythonOperators only receives objects of type callable not strings.
        python_callable = eval(callableFunction),
        op_kwargs = args,
        xcom_push = True,
        dag = dag,
    )
    return task


end = DummyOperator(
    task_id='end',
    dag=dag)



with open('/usr/local/airflow/dags/config_files/dynamicDagConfigFile.yaml') as f:
    configFile = yaml.safe_load(f)

    #Extract file list
    S3Files = configFile['S3Files']

    #In this loop tasks are created for each table defined in the YAML file
    for S3File in S3Files:
        for S3File, fieldName in S3File.items():

            #Remember task id is provided in order to exchange data among tasks generated in dynamic way.
            get_s3_files = createDynamicDAG('{}-getS3Data'.format(S3File), 
                                            'getS3Data', 
                                            {}) #your configs here.

            #Second step is upload S3 to GCS
            upload_s3_toGCS = createDynamicDAG('{}-uploadDataS3ToGCS'.format(S3File), 'uploadDataS3ToGCS', {'previous_task_id':'{}-'})

#write your configs again here like S3 bucket name prefix extra or read from yaml file, and other GCS config.


start >> get_s3_files
get_s3_files >> upload_s3_toGCS
upload_s3_toGCS >> end

बहुत बहुत धन्यवाद। समस्याओं में से एक है तो मेरे पास क्या था अगर कोई नई फाइल नहीं है? जिन समस्याओं का मुझे सामना करना पड़ता है, उनमें से एक यह है कि इस जगह में हमेशा फाइलें होंगी, लेकिन नई फ़ाइलों को खींचने की गारंटी upload_s3_toGCSनहीं होगी , जिसका अर्थ है कि खंड मौजूद नहीं होगा, और एयरफ्लो में त्रुटि होगी।
arcee123

yamlइन सभी फाइलों को जीसीएस पर अपलोड करते ही आप फाइल से फाइलें हटाकर समस्या का समाधान कर सकते हैं, इस तरह से फाइल में केवल नई फाइलें मौजूद रहेंगी yaml। और अगर कोई नई फाइल नहीं है तो yamlफाइल खाली हो जाएगी और कोई डायनेमिक डैग नहीं बनेगी। यही कारण है कि yamlकिसी सूची में फ़ाइलों को संग्रहीत करने की तुलना में फ़ाइल बहुत बेहतर विकल्प है।
अश्विन अग्रवाल

yamlफ़ाइल भी एक तरह से S3 फ़ाइलों के प्रवेश को बनाए रखने, अगर S3 फ़ाइल से कुछ लगता है में मदद GCS पर अपलोड करने के असफल हो जायेगी, तो आप भी एक ध्वज है कि फाइल करने के लिए इसी बनाए रख सकते हैं और फिर अगले DAG रन पर इन का प्रयास करें।
अश्विन अग्रवाल

और अगर कोई नई फाइल नहीं है तो आप ifDAG के सामने एक शर्त रख सकते हैं जो नई फाइलों के लिए जाँच करेगा yamlयदि नई फाइलें हैं तो इसे निष्पादित करें अन्यथा इसे छोड़ दें।
अश्विन अग्रवाल

यहाँ समस्या यह है कि डाउनस्ट्रीम सेट है। अगर डाउनस्ट्रीम वास्तविक नौकरियों के बिना सेट की जाती है (क्योंकि कोई फाइल मौजूद नहीं है), तो यह त्रुटि होगी।
arcee123
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.