package org.smoothbuild.task.exec;
import static org.smoothbuild.lang.message.Messages.containsErrors;
import javax.inject.Inject;
import javax.inject.Provider;
import org.smoothbuild.db.hashed.Hash;
import org.smoothbuild.db.outputs.OutputsDb;
import org.smoothbuild.io.util.SmoothJar;
import org.smoothbuild.lang.value.Value;
import org.smoothbuild.task.base.Output;
import org.smoothbuild.task.base.Task;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hasher;
public class TaskExecutor {
private final HashCode smoothJarHash;
private final OutputsDb outputsDb;
private final TaskReporter reporter;
private final Provider<ContainerImpl> containerProvider;
@Inject
public TaskExecutor(@SmoothJar HashCode smoothJarHash, OutputsDb outputsDb, TaskReporter reporter,
Provider<ContainerImpl> containerProvider) {
this.smoothJarHash = smoothJarHash;
this.outputsDb = outputsDb;
this.reporter = reporter;
this.containerProvider = containerProvider;
}
public <T extends Value> void execute(Task task) {
HashCode hash = taskHash(task);
boolean isAlreadyCached = outputsDb.contains(hash);
if (isAlreadyCached) {
Output output = outputsDb.read(hash, task.resultType());
task.setOutput(output);
} else {
ContainerImpl container = containerProvider.get();
try {
task.execute(container);
} catch (RuntimeException e) {
reporter.reportCrash(e);
throw new ExecutionException();
} finally {
container.destroy();
}
if (task.isCacheable()) {
outputsDb.write(hash, task.output());
}
}
reporter.report(task, isAlreadyCached);
if (containsErrors(task.output().messages())) {
throw new ExecutionException();
}
}
private <T extends Value> HashCode taskHash(Task task) {
Hasher hasher = Hash.newHasher();
hasher.putBytes(smoothJarHash.asBytes());
hasher.putBytes(task.hash().asBytes());
return hasher.hash();
}
}