diff --git a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/BukkitScheduler.java b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/BukkitScheduler.java index b0e20488..4f1c40c1 100644 --- a/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/BukkitScheduler.java +++ b/bukkit/src/main/java/com/github/games647/fastlogin/bukkit/BukkitScheduler.java @@ -25,7 +25,7 @@ */ package com.github.games647.fastlogin.bukkit; -import com.github.games647.fastlogin.core.AsyncScheduler; +import com.github.games647.fastlogin.core.scheduler.AsyncScheduler; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.slf4j.Logger; diff --git a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java index 21a813a5..63950672 100644 --- a/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java +++ b/bungee/src/main/java/com/github/games647/fastlogin/bungee/FastLoginBungee.java @@ -28,7 +28,6 @@ package com.github.games647.fastlogin.bungee; import com.github.games647.fastlogin.bungee.hook.BungeeAuthHook; import com.github.games647.fastlogin.bungee.listener.ConnectListener; import com.github.games647.fastlogin.bungee.listener.PluginMessageListener; -import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.CommonUtil; import com.github.games647.fastlogin.core.hooks.AuthPlugin; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService; @@ -38,6 +37,7 @@ import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChannelMessage; import com.github.games647.fastlogin.core.message.NamespaceKey; import com.github.games647.fastlogin.core.message.SuccessMessage; +import com.github.games647.fastlogin.core.scheduler.AsyncScheduler; import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.shared.PlatformPlugin; import com.google.common.collect.MapMaker; diff --git a/core/src/main/java21/com/github/games647/fastlogin/core/AsyncScheduler.java b/core/src/main/java/com/github/games647/fastlogin/core/scheduler/AbstractAsyncScheduler.java similarity index 54% rename from core/src/main/java21/com/github/games647/fastlogin/core/AsyncScheduler.java rename to core/src/main/java/com/github/games647/fastlogin/core/scheduler/AbstractAsyncScheduler.java index 11a0ead2..14218b9a 100644 --- a/core/src/main/java21/com/github/games647/fastlogin/core/AsyncScheduler.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/scheduler/AbstractAsyncScheduler.java @@ -23,47 +23,31 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.github.games647.fastlogin.core; +package com.github.games647.fastlogin.core.scheduler; import org.slf4j.Logger; +import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; -/** - * This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and - * context switching between threads too. However, we need many threads for blocking HTTP and database calls. - * Nevertheless, this number can be further limited, because the number of actually working database threads - * is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only - * threads. - */ -public class AsyncScheduler { +public abstract class AbstractAsyncScheduler { - private final Logger logger; + protected final Logger logger; + protected final Executor processingPool; + protected final AtomicInteger currentlyRunning = new AtomicInteger(); - private final Executor asyncPool; - - private final AtomicInteger currentlyRunning = new AtomicInteger(); - - public AsyncScheduler(Logger logger, Executor processingPool) { + public AbstractAsyncScheduler(Logger logger, Executor processingPool) { this.logger = logger; - - logger.info("Using optimized green threads with Java 21"); - this.asyncPool = Executors.newVirtualThreadPerTaskExecutor(); + this.processingPool = processingPool; } - public CompletableFuture runAsync(Runnable task) { - return CompletableFuture - .runAsync(() -> process(task), asyncPool) - .exceptionally(error -> { - logger.warn("Error occurred on thread pool", error); - return null; - }); - } + public abstract CompletableFuture runAsync(Runnable task); - private void process(Runnable task) { + public abstract CompletableFuture runAsyncDelayed(Runnable task, Duration delay); + + protected void process(Runnable task) { currentlyRunning.incrementAndGet(); try { task.run(); diff --git a/core/src/main/java/com/github/games647/fastlogin/core/AsyncScheduler.java b/core/src/main/java/com/github/games647/fastlogin/core/scheduler/AsyncScheduler.java similarity index 71% rename from core/src/main/java/com/github/games647/fastlogin/core/AsyncScheduler.java rename to core/src/main/java/com/github/games647/fastlogin/core/scheduler/AsyncScheduler.java index 6775d0c6..d3391594 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/AsyncScheduler.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/scheduler/AsyncScheduler.java @@ -23,13 +23,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.github.games647.fastlogin.core; +package com.github.games647.fastlogin.core.scheduler; import org.slf4j.Logger; +import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicInteger; /** * This limits the number of threads that are used at maximum. Thread creation can be very heavy for the CPU and @@ -38,21 +38,14 @@ import java.util.concurrent.atomic.AtomicInteger; * is limited by the size of our database pool. The goal is to separate concerns into processing and blocking only * threads. */ -public class AsyncScheduler { - - private final Logger logger; - - private final Executor processingPool; - - private final AtomicInteger currentlyRunning = new AtomicInteger(); +public class AsyncScheduler extends AbstractAsyncScheduler { public AsyncScheduler(Logger logger, Executor processingPool) { - this.logger = logger; - + super(logger, processingPool); logger.info("Using legacy scheduler"); - this.processingPool = processingPool; } + @Override public CompletableFuture runAsync(Runnable task) { return CompletableFuture.runAsync(() -> process(task), processingPool).exceptionally(error -> { logger.warn("Error occurred on thread pool", error); @@ -60,12 +53,22 @@ public class AsyncScheduler { }); } - private void process(Runnable task) { - currentlyRunning.incrementAndGet(); - try { - task.run(); - } finally { - currentlyRunning.getAndDecrement(); - } + @Override + public CompletableFuture runAsyncDelayed(Runnable task, Duration delay) { + return CompletableFuture.runAsync(() -> { + currentlyRunning.incrementAndGet(); + try { + Thread.sleep(delay.toMillis()); + process(task); + } catch (InterruptedException interruptedException) { + // restore interrupt flag + Thread.currentThread().interrupt(); + } finally { + currentlyRunning.getAndDecrement(); + } + }, processingPool).exceptionally(error -> { + logger.warn("Error occurred on thread pool", error); + return null; + }); } } diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java index 6a8291ad..46c431d3 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/PlatformPlugin.java @@ -25,8 +25,8 @@ */ package com.github.games647.fastlogin.core.shared; -import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService; +import com.github.games647.fastlogin.core.scheduler.AsyncScheduler; import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.slf4j.Logger; diff --git a/core/src/test/java/com/github/games647/fastlogin/core/AsyncSchedulerTest.java b/core/src/test/java/com/github/games647/fastlogin/core/AsyncSchedulerTest.java index aa217a0b..1bd2afeb 100644 --- a/core/src/test/java/com/github/games647/fastlogin/core/AsyncSchedulerTest.java +++ b/core/src/test/java/com/github/games647/fastlogin/core/AsyncSchedulerTest.java @@ -25,6 +25,7 @@ */ package com.github.games647.fastlogin.core; +import com.github.games647.fastlogin.core.scheduler.AsyncScheduler; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledForJreRange; diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java index 98a24d42..71c76076 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java @@ -25,13 +25,13 @@ */ package com.github.games647.fastlogin.velocity; -import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService; import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService; import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService; import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChannelMessage; import com.github.games647.fastlogin.core.message.SuccessMessage; +import com.github.games647.fastlogin.core.scheduler.AsyncScheduler; import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.shared.PlatformPlugin; import com.github.games647.fastlogin.velocity.listener.ConnectListener; diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java index 7627561b..e9c57369 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java @@ -53,11 +53,11 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.geysermc.floodgate.api.player.FloodgatePlayer; import java.net.InetSocketAddress; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.UUID; -import java.util.concurrent.TimeUnit; public class ConnectListener { @@ -167,10 +167,9 @@ public class ConnectListener { // In this case it means that the force command (plugin message) is already received and processed while // player is still in the login phase and reported to be offline. Runnable loginTask = new ForceLoginTask(plugin.getCore(), player, server, session); - plugin.getProxy().getScheduler() - .buildTask(plugin, loginTask) - .delay(1L, TimeUnit.SECONDS) // Delay at least one second, otherwise the login command can be missed - .schedule(); + + // Delay at least one second, otherwise the login command can be missed + plugin.getScheduler().runAsyncDelayed(loginTask, Duration.ofSeconds(1)); } @Subscribe diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java index 48bd6210..b64bfae6 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java @@ -35,8 +35,8 @@ import com.velocitypowered.api.proxy.server.RegisteredServer; import org.geysermc.floodgate.api.player.FloodgatePlayer; import java.net.InetSocketAddress; +import java.time.Duration; import java.util.UUID; -import java.util.concurrent.TimeUnit; public class FloodgateAuthTask extends FloodgateManagement { @@ -62,10 +62,7 @@ public class FloodgateAuthTask // In this case it means that the force command (plugin message) is already received and processed while // player is still in the login phase and reported to be offline. Runnable loginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session, forcedOnlineMode); - core.getPlugin().getProxy().getScheduler() - .buildTask(core.getPlugin(), () -> core.getPlugin().getScheduler().runAsync(loginTask)) - .delay(1L, TimeUnit.SECONDS) // Delay at least one second, otherwise the login command can be missed - .schedule(); + core.getPlugin().getScheduler().runAsyncDelayed(loginTask, Duration.ofSeconds(1)); } @Override