All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.convergence_platform.common.tasks.TaskExecutionEngine Maven / Gradle / Ivy

Go to download

Holds the common functionality needed by all Convergence Platform-based services written in Java.

The newest version!
package io.convergence_platform.common.tasks;

import io.convergence_platform.common.dag.DirectedAcyclicGraph;

import java.util.*;

public class TaskExecutionEngine extends DirectedAcyclicGraph {
    private final int threadCount;
    private final Map sharedMemory = new HashMap<>();
    private List tasks = new ArrayList<>();

    public TaskExecutionEngine() {
        this(4);
    }

    public TaskExecutionEngine(int threadCount) {
        this.threadCount = threadCount;
    }

    public void addTask(SubTask task) {
        tasks.add(task);
    }

    public List getSortedTasks() {
        initialize(tasks);
        return topologicalSort();
    }

    public void setSharedMemoryValue(String name, Object value) {
        synchronized (sharedMemory) {
            sharedMemory.put(name, value);
        }
    }

    public Object getSharedMemoryValue(String name) {
        Object result = null;

        synchronized (sharedMemory) {
            result = sharedMemory.get(name);
        }

        return result;
    }

    public boolean execute() {
        validate();

        initialize(tasks);
        List executionOrder = topologicalSort();
        Set finishedTasks = new HashSet<>();
        Set failedTasks = new HashSet<>();

        List threads = createEngineThreads(executionOrder, finishedTasks, failedTasks);
        while (shouldWait(threads, failedTasks, finishedTasks)) {
            waitFor(500);
        }

        markThreadsAsFinished(threads);
        waitUntilAllThreadsFinish(threads);

        return failedTasks.size() == 0 && finishedTasks.size() == tasks.size();
    }

    private void validate() {
        validateAllDependenciesInTaskList();
    }

    private void validateAllDependenciesInTaskList() {
        Set allTasks = new HashSet<>();

        for (SubTask t : tasks) {
            allTasks.add(t);
            allTasks.addAll(t.getDependencies());
        }

        if (!new HashSet<>(tasks).containsAll(allTasks)) {
            throw new RuntimeException("All task dependencies should be added to the DAG engine.");
        }
    }

    private void markThreadsAsFinished(List threads) {
        for (TaskExecutionEngineThread t : threads) {
            t.markFinished();
        }
    }

    private void waitUntilAllThreadsFinish(List threads) {
        boolean allTerminated = false;
        long endTime = System.currentTimeMillis() + 1000 * 60 * 5;

        while (!allTerminated && System.currentTimeMillis() < endTime) {
            allTerminated = true;

            for (TaskExecutionEngineThread t : threads) {
                allTerminated = allTerminated && t.isThreadTerminated();
            }

            if (!allTerminated) {
                waitFor(1000);
            }
        }
    }

    private void waitFor(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
        }
    }

    private boolean shouldWait(List threads, Set failedTasks, Set finishedTasks) {
        if (failedTasks.size() != 0) return false;
        return finishedTasks.size() != tasks.size();
    }

    private List createEngineThreads(List executionOrder, Set finishedTasks, Set failedTasks) {
        List result = new ArrayList<>();

        for (int i = 0; i < threadCount; i++) {
            TaskExecutionEngineThread thread = new TaskExecutionEngineThread(executionOrder, finishedTasks, failedTasks);
            thread.start();
            result.add(thread);
        }

        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy