Проблема высокого уровня. Из-за существующего дизайна конвейеров и принципиальной разницы между управлением зависимостями в ADF V1 (т. Е. С помощью входных наборов данных / срезов) и ADF V2 (с помощью триггеров и цепочек операций) мы попадаем в круговую зависимость вопрос. В ADF V1 мы можем установить зависимость sh между конвейерами, просто используя выходной набор данных активности одного конвейера в качестве входного набора данных активности другого конвейера. Но в ADFV2 мы используем триггеры для запуска конвейера. И то же самое с помощью триггеров попадает в циклические ссылки.
Примеры:
В ADF V1:
Конвейеры: AGetData, AProcessData, BGetData, BProcessData - Интервал планирования всех наборов данных составляет 1 час. Время начала одинаково для всех трубопроводов. Здесь AGetData и AProcessData логически связаны с сущностью A и BGetData и BProcessData логически связаны с сущность B . И ProcessData конвейеры запускаются после GetData конвейеров для любого объекта.
Зависимости:
a. AGetData зависит от выходного набора данных предыдущего прогона AProcessData - интервал составляет 1 час.
b. AProcessData зависит от выходного набора данных текущего прогона AGetData и также зависит от 1 выходного набора данных активности в BProcessData (не последний выходной набор данных активности, но выходной набор данных некоторая активность между конвейером BProcessData ). c. BGetData зависит от конечного (последнего действия) выходного набора данных предыдущего прогона AProcessData и конечного (последнего действия) выходного набора данных предыдущего прогона BProcessData .
В ADF V2:
Трубопроводы: A и B. Мы объединили AGetData и AProcessData в A и BGetData и BProcessData в B. Действия объединены таким образом, что ProcessData действия выполняются после GetData действий (аналогично ADF v1 в плане упорядочения).
Кроме того, в ADFV2 мы не создали отдельные наборы данных для каждого действия. У нас есть 2 набора данных - указывающих на источник и место назначения - которые мы повторно используем во всех действиях. В ADFV1 у нас были отдельные наборы данных, созданные для каждого действия. И мы установили зависимости между конвейерами, используя эти наборы данных / срезы данных.
Кроме того, в ADFV2 мы поддерживаем метаданные активности в таблице конфигурации в БД для каждого конвейера, и во время работы конвейера мы читаем строки из этой таблицы и Выполните эти действия (например, Копирование, запуск хранимой процедуры) внутри ForEach Activity.
Также управление цепочками / зависимостями осуществляется с помощью записи в столбце с именем ExecutionLevel. Каждая строка имеет уровень выполнения - например, 1, 2, 3, ... и действия одного уровня выполнения выполняются только после выполнения действий предыдущего уровня выполнения. Действия одного уровня выполнения выполняются параллельно. В соответствии с этим, конвейер управляется Конфигурацией БД, и большинство вещей являются динамическими c по сравнению с v1 - (поскольку у нас нет отдельных наборов данных для каждого действия и длинных конвейеров, отображаемых в пользовательском интерфейсе).
Мы регистрируем каждое из наших конвейерных выполнений в таблице БД. Здесь оно обозначается как ExecutionLogs . Эти журналы фиксируют, какое действие было выполнено, какое действие не удалось, и т. Д. c. для каждого запуска конвейера.
Теперь перейдем к пункту о поддержании зависимостей в ADFV2.
В разделе зависимостей выше: для точки а) самостоятельная зависимость от падающего окна Триггер помогает. Для точек b и c, если мы попытаемся создать каждый триггер для конвейера A и B, мы попадем в круговые зависимости.
Например: T1 - триггер для A, T2 - триггер для B.
Здесь T1 является независимым и также зависит от T2 - на основе упомянутых выше зависимостей (одно из действий конвейера A зависит от вывода вывода активности конвейера B) Кроме того, T2 является независимым и также зависит от T1 - как B зависит от последнего запуска A (именно здесь возникает циклическая зависимость). В ADF v1 то же самое управлялось через наборы входных данных как зависимости.
Таким образом, один из подходов заключается в следующем: Настройка односторонней зависимости с помощью триггеров (T1 зависит от последнего запуска самого себя, T2 зависит от последнего запуска самого себя и последнего запуска T1) и имеет параметр До активности в конвейере A, который проверяет ( с помощью ссылки ExecutionLogs ), если текущий запуск конвейера B завершил выполнение действия, от которого зависит конвейер A. Поскольку мы читаем метаданные активности из таблицы и выполняем эти действия динамически, мы будем управлять дополнительными столбцами для зависимостей - например, если у нас есть значение столбца для зависимого конвейера и зависимая активность для данной строки для конвейера A, тогда пока конвейер A выполняется, в какой-то момент он проверит значения этих столбцов, связанных с зависимостями. Если он находит значение, заданное для какой-либо строки, он будет работать до тех пор, пока не будет выполнено действие, которое будет запрашивать журналы, например ExecutionLogs , чтобы проверить, есть ли запись для: состояние завершения зависимого действия в конвейере B для его последнего выполнения ( последний запуск может быть идентифицирован по максимальному идентификатору выполнения для данного конвейера в таблице ExecutionLogs ). Если запись найдена, конвейер A продолжит выполнение следующего действия в конвейере, иначе он будет ожидать и перепроверять условие через определенные интервалы c.
Приведенное выше решение является лишь одним из подходов, но, похоже, не является более чистым. Любые идеи об управлении этими типами зависимостей в ADF V2 были бы действительно полезны.