Skip to content

Commit

Permalink
Use a separated ScheduledThreadPoolExecutor for the SmartCachedYamlFi…
Browse files Browse the repository at this point in the history
…leHolder because scheduling too many things sucks
  • Loading branch information
EverNife committed Aug 9, 2024
1 parent 8a6578d commit 2fdc9a7
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package br.com.finalcraft.evernifecore.config.yaml.caching;

import br.com.finalcraft.evernifecore.config.yaml.helper.CfgExecutor;
import br.com.finalcraft.evernifecore.config.yaml.helper.ConfigHelper;
import br.com.finalcraft.evernifecore.scheduler.FCScheduler;
import org.simpleyaml.configuration.file.YamlFile;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class SmartCachedYamlFileHolder implements IHasYamlFile {

private static final long SECONDS_OF_CACHE = TimeUnit.MINUTES.toSeconds(5);
private static final long MINUTES_OF_CACHE = 5;

private YamlFile yamlFile;
private long lastUsed = 0;
Expand All @@ -21,12 +21,12 @@ public class SmartCachedYamlFileHolder implements IHasYamlFile {
private String contentAsString;
private boolean hasComments;

private final ReentrantLock lock = new ReentrantLock();
private transient ScheduledFuture<?> scheduledFuture;

public SmartCachedYamlFileHolder(YamlFile yamlFile) {
this.yamlFile = yamlFile;
this.hasComments = yamlFile.options().useComments();
scheduleExpirationRunnable(TimeUnit.MINUTES.toSeconds(3));//Do a Faster first lookup
scheduleExpirationRunnable((int) Math.ceil(MINUTES_OF_CACHE / 2d), TimeUnit.MINUTES); //Do a Faster first lookup
}

@Override
Expand All @@ -42,7 +42,7 @@ public synchronized YamlFile getYamlFile() {
} catch (IOException e) {
throw new RuntimeException("Failed to Re-Read a SmartCached YamlFile, this should never happen!!!! ?!?!?!", e);
}
scheduleExpirationRunnable(SECONDS_OF_CACHE);
scheduleExpirationRunnable(MINUTES_OF_CACHE, TimeUnit.MINUTES);
}
return yamlFile;
}
Expand All @@ -61,20 +61,32 @@ public synchronized void cacheToString(){
this.yamlFile = null;//free for GC to collect
}

public void scheduleExpirationRunnable(long secondsToWait){
FCScheduler.getScheduler().schedule(() -> {
if (this.innerGetYamlFile() == null){
return;//It means was cached to string manually
public void scheduleExpirationRunnable(long delay, TimeUnit timeUnit){
if (scheduledFuture != null && !scheduledFuture.isCancelled() && !scheduledFuture.isDone()){
scheduledFuture.cancel(false);
scheduledFuture = null;
}

if (delay < 0){
if (this.innerGetYamlFile() != null) {
cacheToString();
}
return;
}

boolean usedAtLeastOnceOnTheLastThreeMinutes = System.currentTimeMillis() < getLastUsed() + TimeUnit.SECONDS.toMillis(SECONDS_OF_CACHE);
this.scheduledFuture = CfgExecutor.getScheduler().schedule(() -> {
if (this.innerGetYamlFile() != null) {

boolean usedAtLeastOnceOnTheLastThreeMinutes = System.currentTimeMillis() < getLastUsed() + TimeUnit.MINUTES.toMillis(MINUTES_OF_CACHE);

if (usedAtLeastOnceOnTheLastThreeMinutes) {
//Lets do nothing, just check again in MINUTES_OF_CACHE minutes
scheduleExpirationRunnable(MINUTES_OF_CACHE, TimeUnit.MINUTES);
} else {
cacheToString();
}

if (usedAtLeastOnceOnTheLastThreeMinutes) {
//Lets do nothing, just check again in 3 minutes
scheduleExpirationRunnable(SECONDS_OF_CACHE);
} else {
cacheToString();
}
}, secondsToWait, TimeUnit.SECONDS);
}, delay, timeUnit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.logging.Logger;

public class CfgExecutor {

private static final Logger logger = Logger.getLogger("CfgExecutor");

private static final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(10);

public static ScheduledThreadPoolExecutor getScheduler() {
return scheduler;
}

public static ExecutorService EXECUTOR_SERVICE;
static {
createExecutorService();
Expand All @@ -38,14 +41,14 @@ public static synchronized void shutdownExecutor(){
EXECUTOR_SERVICE.shutdown();
boolean success = EXECUTOR_SERVICE.awaitTermination(30, TimeUnit.SECONDS);
if (!success){
logger.warning("Failed to close ConfigHelper Scheduller, TimeOut of 30 seconds Reached, this is really bad! Terminating all of them now!");
logger.warning("Failed to close ConfigHelper Scheduler, TimeOut of 30 seconds Reached, this is really bad! Terminating all of them now!");
EXECUTOR_SERVICE.shutdownNow();
}
} catch (InterruptedException e){
e.printStackTrace();
}
}else {
throw new IllegalStateException("Tried to stop the ConfigHelper Scheduller while it was not running at all!");
throw new IllegalStateException("Tried to stop the ConfigHelper Scheduler while it was not running at all!");
}
}
}

0 comments on commit 2fdc9a7

Please sign in to comment.