some improvements, including work directly with production jobs
This commit is contained in:
parent
e0e95047dc
commit
bb75899bb9
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>tv.mangrana</groupId>
|
<groupId>tv.mangrana</groupId>
|
||||||
<artifactId>mangrana-commons</artifactId>
|
<artifactId>mangrana-commons</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>3.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>8</maven.compiler.source>
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
|
|
@ -5,10 +5,28 @@ import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
public class LocalEnvironmentManager {
|
public class LocalEnvironmentManager {
|
||||||
|
|
||||||
private LocalEnvironmentManager(){}
|
public enum LocalMode {NAS, PC, CONTABO}
|
||||||
|
|
||||||
|
static LocalMode mode;
|
||||||
|
static {
|
||||||
|
mode = LocalMode.PC;
|
||||||
|
}
|
||||||
|
|
||||||
public static final String PROJECT_ROOT = System.getProperty("user.dir");
|
public static final String PROJECT_ROOT = System.getProperty("user.dir");
|
||||||
|
|
||||||
|
public static final String REMOTE_ACCESS_FOLDER_FROM_MAC = "Volumes";
|
||||||
|
|
||||||
|
public static void setLocalMode(String mode) {
|
||||||
|
try {
|
||||||
|
LocalEnvironmentManager.mode = LocalMode.valueOf(mode);
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRootPath() {
|
||||||
|
return mode.equals(LocalMode.PC) ? PROJECT_ROOT : REMOTE_ACCESS_FOLDER_FROM_MAC;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isLocal () {
|
public static boolean isLocal () {
|
||||||
String envVar = System.getenv("ENV");
|
String envVar = System.getenv("ENV");
|
||||||
return
|
return
|
||||||
|
@ -16,4 +34,12 @@ public class LocalEnvironmentManager {
|
||||||
&& envVar.equals("local");
|
&& envVar.equals("local");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isWorkingWithProdFiles () {
|
||||||
|
return mode.equals(LocalMode.CONTABO) || !isLocal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalMode getLocalMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public abstract class JobFile<E> {
|
||||||
return getLocalNameIfNecessary(this);
|
return getLocalNameIfNecessary(this);
|
||||||
}
|
}
|
||||||
private String getLocalNameIfNecessary(JobLocation location) {
|
private String getLocalNameIfNecessary(JobLocation location) {
|
||||||
if (LocalEnvironmentManager.isLocal()
|
if (LocalEnvironmentManager.isLocal() && !LocalEnvironmentManager.isWorkingWithProdFiles()
|
||||||
&& (location.equals(JobLocation.PATH_TODO) || location.equals(JobLocation.PATH_DOING))) {
|
&& (location.equals(JobLocation.PATH_TODO) || location.equals(JobLocation.PATH_DOING))) {
|
||||||
return LOCAL_WORKING_PATH;
|
return LOCAL_WORKING_PATH;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static tv.mangrana.config.LocalEnvironmentManager.PROJECT_ROOT;
|
import static tv.mangrana.config.LocalEnvironmentManager.getLocalMode;
|
||||||
import static tv.mangrana.jobs.JobFile.JobLocation;
|
import static tv.mangrana.jobs.JobFile.JobLocation;
|
||||||
import static tv.mangrana.jobs.JobFile.JobLocation.PATH_DOING;
|
import static tv.mangrana.jobs.JobFile.JobLocation.PATH_DOING;
|
||||||
import static tv.mangrana.jobs.JobFile.JobLocation.PATH_TODO;
|
import static tv.mangrana.jobs.JobFile.JobLocation.PATH_TODO;
|
||||||
|
@ -21,12 +21,14 @@ public class JobFileManager {
|
||||||
|
|
||||||
private JobFileManager(){}
|
private JobFileManager(){}
|
||||||
|
|
||||||
public static final String JOBS_FOLDER = "jobs";
|
static final String JOBS_FOLDER = "jobs";
|
||||||
|
static final String ALT_JOBS_FOLDER = "jobs-1";
|
||||||
|
|
||||||
public enum JobFileType {
|
public enum JobFileType {
|
||||||
SONARR_JOBS("sonarr"),
|
SONARR_JOBS("sonarr"),
|
||||||
RADARR_JOBS("radarr"),
|
RADARR_JOBS("radarr"),
|
||||||
TRANSMISSION_JOBS("transm");
|
TRANSMISSION_JOBS("transm");
|
||||||
|
|
||||||
private final String folderName;
|
private final String folderName;
|
||||||
JobFileType(String folderName) {
|
JobFileType(String folderName) {
|
||||||
this.folderName=folderName;
|
this.folderName=folderName;
|
||||||
|
@ -35,7 +37,6 @@ public class JobFileManager {
|
||||||
return folderName;
|
return folderName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void moveUncompletedJobsToRetry(JobFileType appType) {
|
public static void moveUncompletedJobsToRetry(JobFileType appType) {
|
||||||
File jobsDir = new File(getAbsolutePath(PATH_DOING, appType));
|
File jobsDir = new File(getAbsolutePath(PATH_DOING, appType));
|
||||||
File[] files = jobsDir.listFiles();
|
File[] files = jobsDir.listFiles();
|
||||||
|
@ -64,10 +65,16 @@ public class JobFileManager {
|
||||||
|
|
||||||
public static String getAbsolutePath(JobLocation location, JobFileType appType) {
|
public static String getAbsolutePath(JobLocation location, JobFileType appType) {
|
||||||
String jobsFolder = LocalEnvironmentManager.isLocal()
|
String jobsFolder = LocalEnvironmentManager.isLocal()
|
||||||
? addSubFolder(rootFolder(PROJECT_ROOT), JOBS_FOLDER)
|
? addSubFolder(rootFolder(LocalEnvironmentManager.getRootPath()), getLocalJobsFolder())
|
||||||
: rootFolder(JOBS_FOLDER);
|
: rootFolder(JOBS_FOLDER);
|
||||||
String appFolderPath = addSubFolder(jobsFolder, appType.getFolderName());
|
String appFolderPath = addSubFolder(jobsFolder, appType.getFolderName());
|
||||||
return addSubFolder(appFolderPath, location.getFolderName());
|
return addSubFolder(appFolderPath, location.getFolderName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static String getLocalJobsFolder() {
|
||||||
|
return getLocalMode().equals(LocalEnvironmentManager.LocalMode.CONTABO)
|
||||||
|
? ALT_JOBS_FOLDER
|
||||||
|
: JOBS_FOLDER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,16 +40,25 @@ public class PlexCommandLauncher {
|
||||||
// new PlexCommandLauncher(new CommonConfigFileLoader()).scanByPath(toRefresh);
|
// new PlexCommandLauncher(new CommonConfigFileLoader()).scanByPath(toRefresh);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public void scanSerieByPath(String fullDestinationPath) {
|
public boolean scanSerieByPath(String fullDestinationPath) {
|
||||||
scanByPath(getPlexSeriePath2Refresh(fullDestinationPath));
|
try {
|
||||||
|
return scanByPath(getPlexSeriePath2Refresh(fullDestinationPath));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public boolean scanMovieByPath(String fullDestinationPath) {
|
||||||
|
try {
|
||||||
|
return scanByPath(getPlexMoviePath2Refresh(fullDestinationPath));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
public void scanMovieByPath(String fullDestinationPath) {
|
|
||||||
scanByPath(getPlexMoviePath2Refresh(fullDestinationPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scanByPath(String plexPathToRefresh) {
|
private boolean scanByPath(String plexPathToRefresh) {
|
||||||
|
boolean ok = true;
|
||||||
String plexRefreshURL = getPlexRefreshURL(plexPathToRefresh);
|
String plexRefreshURL = getPlexRefreshURL(plexPathToRefresh);
|
||||||
if (plexRefreshURL==null) return;
|
if (plexRefreshURL==null) return false;
|
||||||
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
|
||||||
|
|
||||||
HttpUriRequest httpGET = RequestBuilder.get()
|
HttpUriRequest httpGET = RequestBuilder.get()
|
||||||
|
@ -64,7 +73,9 @@ public class PlexCommandLauncher {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.nHLog("Some error has happened using the URL <{0}>", plexRefreshURL);
|
logger.nHLog("Some error has happened using the URL <{0}>", plexRefreshURL);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
ok = false;
|
||||||
}
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlexSeriePath2Refresh(String fullDestinationPath) {
|
public String getPlexSeriePath2Refresh(String fullDestinationPath) {
|
||||||
|
@ -85,6 +96,7 @@ public class PlexCommandLauncher {
|
||||||
.setUri(new URI(plexSectionsURL))
|
.setUri(new URI(plexSectionsURL))
|
||||||
.addParameter("X-Plex-Token", config.getConfig(PLEX_TOKEN))
|
.addParameter("X-Plex-Token", config.getConfig(PLEX_TOKEN))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try (CloseableHttpResponse httpResponse = httpclient.execute(httpGET)) {
|
try (CloseableHttpResponse httpResponse = httpclient.execute(httpGET)) {
|
||||||
|
|
||||||
final HttpEntity entity = httpResponse.getEntity();
|
final HttpEntity entity = httpResponse.getEntity();
|
||||||
|
@ -107,12 +119,16 @@ public class PlexCommandLauncher {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPlexRefreshURL(String fullDestinationPath) {
|
private String getPlexRefreshURL(String fullDestinationPath) {
|
||||||
|
try {
|
||||||
String sectionId = sectionResolver.resolveSectionByPath(fullDestinationPath);
|
String sectionId = sectionResolver.resolveSectionByPath(fullDestinationPath);
|
||||||
if (sectionId==null) return null;
|
if (sectionId==null) return null;
|
||||||
String host = config.getConfig(PLEX_HOST);
|
String host = config.getConfig(PLEX_HOST);
|
||||||
String uriFormat = config.getConfig(PLEX_SECTION_REFRESH_URI);
|
String uriFormat = config.getConfig(PLEX_SECTION_REFRESH_URI);
|
||||||
String uri = uriFormat.replaceFirst("\\{section_id}", sectionId);
|
String uri = uriFormat.replaceFirst("\\{section_id}", sectionId);
|
||||||
return HTTPS.getMark() + host + uri;
|
return HTTPS.getMark() + host + uri;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPlexSectionsURL() {
|
private String getPlexSectionsURL() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class Output {
|
||||||
}
|
}
|
||||||
public static void log (String msg, Object... params) {
|
public static void log (String msg, Object... params) {
|
||||||
try {
|
try {
|
||||||
if (params.length>1)
|
if (params.length>0)
|
||||||
log(msg(msg, params));
|
log(msg(msg, params));
|
||||||
else
|
else
|
||||||
log(msg);
|
log(msg);
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package tv.mangrana.utils;
|
||||||
|
|
||||||
|
import tv.mangrana.exception.TooMuchTriesException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static tv.mangrana.utils.Output.getCurrentTime;
|
||||||
|
import static tv.mangrana.utils.Output.msg;
|
||||||
|
import static tv.mangrana.utils.Waiter.waitMinutes;
|
||||||
|
import static tv.mangrana.utils.Waiter.waitSeconds;
|
||||||
|
|
||||||
|
public class RetryEngine<D> {
|
||||||
|
|
||||||
|
private final String title;
|
||||||
|
private final int minutesToWait;
|
||||||
|
private final ChildrenRequirements<D> childrenRequirements;
|
||||||
|
private final Consumer<String> logger;
|
||||||
|
|
||||||
|
public static class ChildrenRequirements<D> {
|
||||||
|
final int children;
|
||||||
|
final Function<D, List<D>> retriever;
|
||||||
|
final Function<D, Boolean> constraint;
|
||||||
|
final int childrenLookupMaxRetries;
|
||||||
|
|
||||||
|
public ChildrenRequirements(int childrenMustHave, Function<D, List<D>> childrenRetriever, Function<D, Boolean> constraint, int childrenLookupMaxRetries){
|
||||||
|
this.children = childrenMustHave;
|
||||||
|
this.retriever = childrenRetriever;
|
||||||
|
this.constraint = constraint;
|
||||||
|
this.childrenLookupMaxRetries = childrenLookupMaxRetries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RetryEngine(String title, int minutesToWait, Consumer<String> logger) {
|
||||||
|
this(title, minutesToWait, null, logger);
|
||||||
|
}
|
||||||
|
public RetryEngine(String title, int minutesToWait, ChildrenRequirements<D> childrenRequirements, Consumer<String> logger) {
|
||||||
|
this.title = title;
|
||||||
|
this.minutesToWait = minutesToWait;
|
||||||
|
this.childrenRequirements = childrenRequirements;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public D tryUntilGotDesired(Supplier<D> tryToGet, final int tooMuchTriesThreshold) throws TooMuchTriesException {
|
||||||
|
AtomicInteger loopCount = new AtomicInteger(1);
|
||||||
|
D desired = null;
|
||||||
|
boolean waitForChildren = Optional.ofNullable(childrenRequirements).map(req -> req.children > 0).orElse(false);
|
||||||
|
while (Objects.isNull(desired)) {
|
||||||
|
try {
|
||||||
|
desired = tryToGet.get();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log("An error was occurred when trying to get element but it only will count as a failed try. The stacktrace will be printed.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (Objects.isNull(desired)) {
|
||||||
|
if (loopCount.get() >= tooMuchTriesThreshold) {
|
||||||
|
throw new TooMuchTriesException("Too much tries when retrieving desired element");
|
||||||
|
}
|
||||||
|
if (loopCount.get() == 1) log(msg("The element was not found yet and will retry every {0} minutes - {1}", minutesToWait, getCurrentTime()));
|
||||||
|
loopCount.incrementAndGet();
|
||||||
|
waitMinutes(minutesToWait);
|
||||||
|
} else if (waitForChildren) {
|
||||||
|
childrenCheckingLoop(desired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("the try was satisfied and will return the desired element/s");
|
||||||
|
return desired;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void childrenCheckingLoop(D got) {
|
||||||
|
AtomicInteger loopCount = new AtomicInteger(1);
|
||||||
|
boolean waitForChildren=true;
|
||||||
|
boolean childrenConstraintSatisfied = childrenRequirements.constraint == null;
|
||||||
|
while (waitForChildren) {
|
||||||
|
List<D> children = childrenRequirements.retriever.apply(got);
|
||||||
|
if (children.size() < childrenRequirements.children) {
|
||||||
|
if (loopCount.get() >= childrenRequirements.childrenLookupMaxRetries) {
|
||||||
|
log(msg("Too much tries when retrieving children from {0} while current is {1} and expected {2}. However, we will work with the files we have.",
|
||||||
|
got.getClass().getSimpleName(), children.size(), childrenRequirements.children));
|
||||||
|
waitForChildren = false;
|
||||||
|
}
|
||||||
|
if (loopCount.get() == 1)
|
||||||
|
log(msg("Not enough children yet ({2} vs {3}) and will retry in {0} minutes - {1}",
|
||||||
|
minutesToWait, getCurrentTime(), children.size(), childrenRequirements.children));
|
||||||
|
loopCount.incrementAndGet();
|
||||||
|
waitMinutes(minutesToWait);
|
||||||
|
} else {
|
||||||
|
if (!childrenConstraintSatisfied) {
|
||||||
|
childrenConstraintSatisfied = children.stream().allMatch(childrenRequirements.constraint::apply);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
waitForChildren = false;
|
||||||
|
waitSeconds(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void log (String msg) {
|
||||||
|
logger.accept(msg("-|*|RetryEngine.{0}|*|- {1}", title, msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue