Облегченная среда выполнения "система сборки" - PullRequest
4 голосов
/ 11 января 2012

Я недавно работал над рефакторингом системы, которая обрабатывает пакеты клиентских данных. Система выполняет серию шагов, каждый из которых использует файлы предыдущих шагов (и иногда данные в памяти), и выдает собственный вывод в виде файлов или данных. Иногда выходные данные для определенного шага уже доступны. Я должен быть осторожным, чтобы в случае сбоя одного шага мы продолжали выполнять все возможные шаги (те, которые не зависят от неудачного шага), чтобы окончательный вывод был максимально полным. Кроме того, не все шаги должны выполняться во всех ситуациях.

Раньше все отношения были неявными в структуре кода. Например:

void processClientData() {
    try {
        processA();
    } catch(Exception e) {
        log.log(Level.SEVERE, "exception occured in step A", e);
        processC(); // C doesn't depend on A, so we can still run it.
        throw e;
    }

    processB();
    processC();
    //etc... for ~20 steps
}

Я изменил это, чтобы сделать зависимости явными, единообразной обработки ошибок и т. Д., Введя Задачи:

public interface Task {
    List<Task> getDependencies();
    void execute(); //only called after all dependencies have been executed
}

public class TaskRunner {
    public void run(Set<Task> targets) {
        // run the dependencies and targets ala ANT
        // make sure to run all possible tasks on the "road" to targets
        // ...
    }
}

Это начинает сильно походить на очень разветвленную версию системы сборки с управлением зависимостями (ANT, наиболее мне знакомый). Я не хочу использовать ANT для такого рода вещей, и, конечно же, я не хочу писать XML.

Моя система работает и работает (в основном), но она все еще выглядит немного взломанной, и с тех пор я размышлял над тем, насколько я ненавижу изобретать велосипед. Я ожидал бы, что это довольно распространенная проблема, которая много раз решалась людьми умнее меня. Увы, несколько часов поиска в Google ничего не дали

Существует ли библиотека, которая реализует подобные вещи, не будучи действительно тяжелой системой сборки? Я также был бы признателен за любые указатели, включая библиотеки на других языках (или даже новые системы), на которые я должен был бы вдохновиться.

РЕДАКТИРОВАТЬ: Я ценю предложения (и я буду уделять им должное внимание), но я действительно не ищу "систему сборки" как таковую. То, что я ищу, - это что-то более похожее на ядро ​​ системы сборки, которое я мог бы просто вызывать напрямую из Java и использовать в качестве небольшой библиотеки с минимальными издержками для выполнения упомянутого анализа зависимостей, выполнения задач и результирующее управление ресурсами. Как я уже сказал, у меня есть существующий (работающий) код на чистой Java, и я не хочу вводить XML и весь багаж, который идет с ним, без очень веских причин.

Ответы [ 5 ]

2 голосов
/ 11 января 2012

По своей сути, система сборки делает 3 вещи. Он управляет зависимостями, проверяет, «что-то создано» или нет, и «строит» то, что не построено.

Управление зависимостями - это не просто топологическая сортировка. Остальные перебирают задания в зависимом порядке и обрабатывают их.

Вы можете легко создать что-то вроде:

BuildSystem bs = new BuildSystem();
bs.addTask(new Task1());
bs.addTask(new Task...);
bs.addTask(new TaskN());

bs.build();

public void build() {
    List<Task> sortedTasks = topologicalTaskSort(tasks);
    for(Task t : sortedTasks) {
        if (t.needsBuilding()) {
            t.execute();
        }
    }
}

Если вам не нужно выводить список задач из списка задач, то нет причин для файла XML или чего-либо еще.

Топологическая сортировка позволяет вам просто добавлять задачи в список и позволять системе разбирать вещи. Не проблема с 4 задачами, больше проблема с десятками задач.

Сортировка завершается неудачно, если она обнаруживает цикл зависимости, поэтому вы получаете этот элемент управления.

Что-то вроде этого "слишком просто", чтобы нуждаться в каркасе. Я не знаю, как вы сейчас справляетесь с зависимостями.

1 голос
/ 04 марта 2012

Посмотрите на фреймворк / соединение jsr166.Мне кажется, это именно то, что вы пытаетесь достичь.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ForkJoinTask.html

Это включено в JDK7, но доступно в качестве отдельного jar для 5 и 6. Если я не былНа моем планшете я бы написал более полный пример.Может быть, кто-то еще может расшириться за это время.

public class DependencyTreeTask extends RecursiveAction {

  private final List<DependencyTreeTask> dependencies = new ArrayList<Task>();

  public void addDependency(DependencyTreeTask t) { dependencies.add(t) }

  public void compute() {
    invokeAll(dependencies);
  }

}

...
// build tree...
DependencyTreeTask root = ...
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(root);

Вы также должны позаботиться о том, что ваш граф не связан, но существует известный набор алгоритмов для определения этого.

1 голос
/ 11 января 2012

Я бы подумал написать плагин для Maven, это не так сложно и не намного легче , потому что вам нужно только предоставить соответствующую специальную логику.Вся инфраструктура предоставлена ​​Maven.Maven 3 даже даст вам такие вещи, как параллельные сборки, где ваш плагин поддерживает его бесплатно, среди всего прочего, что он предоставляет.

Одной из основных целей Maven 3 было переписать, чтобы сделать его максимально простымпо возможности встроить механизм рабочего процесса в ваши собственные проекты.

0 голосов
/ 08 мая 2017

Ваш код напоминает мне о iwant , движке сборки Java, который я разрабатывал.Вы можете объявить определения цели с помощью зависимостей, используя свободный Java, и в дополнение к обычному использованию из командной строки (или скрипта Ant) вы также можете встроить свою сборку в Java-программу.

0 голосов
/ 11 января 2012

Я слышал, что Дженкинса использовали для такого рода вещей в дополнение к его основной роли 'системы сборки'.Я только начал использовать Дженкинс, поэтому не могу точно сказать, будет ли он делать то, что вам нужно.Я впечатлен этим до сих пор.Он относительно прост в использовании и имеет множество опций конфигурации.Для этого также существует большое количество плагинов.Просто запустите Jenkins и перейдите на страницу плагинов, чтобы просмотреть список и установить их.

...