fixes and timeouts

This commit is contained in:
Anthony Stirling 2024-01-10 00:33:07 +00:00
parent ef12c2f892
commit e717d83f75
3 changed files with 52 additions and 13 deletions

View file

@ -35,15 +35,17 @@ public class FileToPdf {
command.add("weasyprint");
} else {
command.add("wkhtmltopdf");
command.add("--enable-local-file-access");
}
command.add(tempInputFile.toString());
command.add(tempOutputFile.toString());
ProcessExecutorResult returnCode;
if (fileName.endsWith(".zip")) {
if (htmlFormatsInstalled) {
command.add("--allow");
command.add(tempOutputFile.getParent().toString());
// command.add(1, "--allow");
// command.add(2, tempInputFile.getParent().toString());
}
returnCode =
ProcessExecutor.getInstance(ProcessExecutor.Processes.WEASYPRINT)

View file

@ -4,15 +4,22 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProcessExecutor {
private static final Logger logger = LoggerFactory.getLogger(ProcessExecutor.class);
public enum Processes {
LIBRE_OFFICE,
OCR_MY_PDF,
@ -26,7 +33,7 @@ public class ProcessExecutor {
private static final Map<Processes, ProcessExecutor> instances = new ConcurrentHashMap<>();
public static ProcessExecutor getInstance(Processes processType) {
return getInstance(processType, false);
return getInstance(processType, true);
}
public static ProcessExecutor getInstance(Processes processType, boolean liveUpdates) {
@ -43,16 +50,29 @@ public class ProcessExecutor {
case INSTALL_APP -> 1;
case CALIBRE -> 1;
};
return new ProcessExecutor(semaphoreLimit, liveUpdates);
long timeoutMinutes =
switch (key) {
case LIBRE_OFFICE -> 30;
case OCR_MY_PDF -> 30;
case PYTHON_OPENCV -> 30;
case GHOSTSCRIPT -> 5;
case WEASYPRINT -> 30;
case INSTALL_APP -> 60;
case CALIBRE -> 30;
};
return new ProcessExecutor(semaphoreLimit, liveUpdates, timeoutMinutes);
});
}
private final Semaphore semaphore;
private final boolean liveUpdates;
private long timeoutDuration;
private ProcessExecutor(int semaphoreLimit, boolean liveUpdates) {
private ProcessExecutor(int semaphoreLimit, boolean liveUpdates, long timeout) {
this.semaphore = new Semaphore(semaphoreLimit);
this.liveUpdates = liveUpdates;
this.timeoutDuration = timeout;
}
public ProcessExecutorResult runCommandWithOutputHandling(List<String> command)
@ -62,12 +82,12 @@ public class ProcessExecutor {
public ProcessExecutorResult runCommandWithOutputHandling(
List<String> command, File workingDirectory) throws IOException, InterruptedException {
int exitCode = 1;
String messages = "";
int exitCode = 1;
semaphore.acquire();
try {
System.out.print("Running command: " + String.join(" ", command));
logger.info("Running command: " + String.join(" ", command));
ProcessBuilder processBuilder = new ProcessBuilder(command);
// Use the working directory if it's set
@ -91,8 +111,11 @@ public class ProcessExecutor {
String line;
while ((line = errorReader.readLine()) != null) {
errorLines.add(line);
if (liveUpdates) System.out.println(line);
if (liveUpdates) logger.info(line);
}
} catch (InterruptedIOException e) {
logger.warn(
"Error reader thread was interrupted due to timeout.");
} catch (IOException e) {
e.printStackTrace();
}
@ -109,8 +132,11 @@ public class ProcessExecutor {
String line;
while ((line = outputReader.readLine()) != null) {
outputLines.add(line);
if (liveUpdates) System.out.println(line);
if (liveUpdates) logger.info(line);
}
} catch (InterruptedIOException e) {
logger.warn(
"Error reader thread was interrupted due to timeout.");
} catch (IOException e) {
e.printStackTrace();
}
@ -120,8 +146,17 @@ public class ProcessExecutor {
outputReaderThread.start();
// Wait for the conversion process to complete
exitCode = process.waitFor();
boolean finished = process.waitFor(timeoutDuration, TimeUnit.MINUTES);
if (!finished) {
// Terminate the process
process.destroy();
// Interrupt the reader threads
errorReaderThread.interrupt();
outputReaderThread.interrupt();
throw new IOException("Process timeout exceeded.");
}
exitCode = process.exitValue();
// Wait for the reader threads to finish
errorReaderThread.join();
outputReaderThread.join();
@ -130,13 +165,13 @@ public class ProcessExecutor {
if (outputLines.size() > 0) {
String outputMessage = String.join("\n", outputLines);
messages += outputMessage;
System.out.println("Command output:\n" + outputMessage);
logger.info("Command output:\n" + outputMessage);
}
if (errorLines.size() > 0) {
String errorMessage = String.join("\n", errorLines);
messages += errorMessage;
System.out.println("Command error output:\n" + errorMessage);
logger.warn("Command error output:\n" + errorMessage);
if (exitCode != 0) {
throw new IOException(
"Command process failed with exit code "

View file

@ -13,7 +13,9 @@ system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
# customExternalPort: 8000 used for when port mappings do not work correctly
customApplications:
installBookFormats: false # Installs Calibre for book format conversion (For non docker it must be manually downloaded but will need to be true to show in UI)
installAdvancedHtmlToPDF: false # DO NOT USE EXTERNALLY, NOT SAFE! Install wkHtmlToPDF (For non docker it must be manually downloaded but will need to be true to show in UI)
#ui:
# appName: exampleAppName # Application's visible name