Код-ревью Middle ETL, ELT и Airflow спрашивают часто обновлено
Код-ревью: DAG ежедневной выгрузки заказов
Вопрос
Это DAG ежедневной загрузки заказов в хранилище. Найдите проблемы.
from datetime import datetime, timedelta
from airflow import DAG
from airflow.operators.python import PythonOperator
import psycopg2, pandas as pd
conn = psycopg2.connect("host=prod-db user=etl password=Qwerty123")
TABLES = pd.read_sql("select table_name from etl_tables", conn)
def load_orders(**ctx):
day = (datetime.now() - timedelta(days=1)).date()
df = pd.read_sql(f"select * from orders where created_at::date = '{day}'", conn)
dwh.execute("insert into dwh.orders select * from df")
with DAG("orders", start_date=datetime.now(), schedule="@daily") as dag:
PythonOperator(task_id="load", python_callable=load_orders)
Коротко
Почти все проблемы из урока в одном файле: секреты в коде, тяжёлый код на верхнем уровне, период от текущего времени, неидемпотентная вставка, плавающая startdate.
Что должен найти ревьюер
- Безопасностьстрока 6Пароль от боевой базы в коде DAG. Подключения хранятся в Airflow Connections или во внешнем хранилище секретов.
- Производительностьстрока 7Запрос к базе на верхнем уровне файла: выполняется при каждом разборе DAG планировщиком. Логику надо унести внутрь задачи.
- Ошибкастрока 10Период «вчера» от текущего времени: ретрай на следующий день и бэкфилл обработают не тот день. Брать
data_interval_startиdata_interval_endиз контекста. - Ошибкастрока 11Фильтр по
created_atтеряет изменения уже существующих заказов (смену статуса). Нужен инкремент поupdated_atили CDC. - Производительностьстрока 11
created_at::date = ...не использует индекс поcreated_at; лучше полуинтервалcreated_at >= start AND created_at < end. Плюс чтение с боевой базы вместо реплики. - Ошибкастрока 12Неидемпотентная вставка: при ретрае данные за день задвоятся. Нужна перезапись партиции дня или upsert.
- Ошибкастрока 14
start_date=datetime.now(): динамическая дата старта делает расписание непредсказуемым. Нужна фиксированная дата и явныйcatchup. - Стильстрока 15Нет ретраев, таймаута и проверок качества после загрузки; ошибки будут молча доходить до витрин.
Разбор
Почти все проблемы из урока в одном файле: секреты в коде, тяжёлый код на верхнем уровне, период от текущего времени, неидемпотентная вставка, плавающая start_date. Правильная версия берёт подключение из Connections, читает реплику за data_interval по updated_at, пишет в staging и перезаписывает партицию дня, а после загрузки проверяет объём и ключи.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.