From 2404bed85cf5416b215c264f782d860c1a277d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nelson=20Gra=C3=A7a?= Date: Tue, 30 Dec 2025 12:11:16 +0000 Subject: [PATCH] Add minimum online checks for a server to be considered online --- .../pistonqueue/shared/config/Config.java | 12 ++ .../shared/plugin/PistonQueuePlugin.java | 11 +- .../shared/queue/QueueListenerShared.java | 5 +- .../shared/queue/ServerStatusManager.java | 46 ++++++++ .../shared/queue/logic/QueueEnvironment.java | 15 ++- .../queue/logic/KickEventHandlerTest.java | 18 +-- .../shared/queue/logic/QueueCleanerTest.java | 8 +- .../queue/logic/QueueConnectorTest.java | 10 +- .../queue/logic/QueueEntryFactoryTest.java | 10 +- .../queue/logic/QueueMoveProcessorTest.java | 2 +- .../logic/QueuePlacementCoordinatorTest.java | 2 +- .../queue/logic/QueueRecoveryHandlerTest.java | 8 +- .../queue/logic/QueueServerSelectorTest.java | 20 ++-- .../queue/logic/ServerStatusManagerTest.java | 104 ++++++++++++++++++ 14 files changed, 216 insertions(+), 55 deletions(-) create mode 100644 shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/ServerStatusManager.java create mode 100644 shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/ServerStatusManagerTest.java diff --git a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/config/Config.java b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/config/Config.java index 783ba87..88d7c9d 100644 --- a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/config/Config.java +++ b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/config/Config.java @@ -67,6 +67,9 @@ public final class Config { @Comment("It is not recommended to decrease this number (milliseconds)") private int serverOnlineCheckDelay = 500; + @Comment("How many online checks need to be successful before we consider the server online") + private int minOnlineChecks = 3; + @Comment("Where to send the queue position message and what to send.") private boolean positionMessageChat = true; private boolean positionMessageHotBar = false; @@ -207,6 +210,7 @@ public void copyFrom(Config source) { registerTab = source.registerTab; serverIsFullMessage = source.serverIsFullMessage; serverOnlineCheckDelay = source.serverOnlineCheckDelay; + minOnlineChecks = source.minOnlineChecks; positionMessageChat = source.positionMessageChat; positionMessageHotBar = source.positionMessageHotBar; queuePosition = source.queuePosition; @@ -278,6 +282,10 @@ public int serverOnlineCheckDelay() { return serverOnlineCheckDelay; } + public int minOnlineChecks() { + return minOnlineChecks; + } + public boolean positionMessageChat() { return positionMessageChat; } @@ -527,6 +535,10 @@ public void setServerIsFullMessage(String message) { this.serverIsFullMessage = message; } + public void setMinOnlineChecks(int minOnlineChecks) { + this.minOnlineChecks = minOnlineChecks; + } + public void setServerDownKickMessage(String message) { this.serverDownKickMessage = message; } diff --git a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/plugin/PistonQueuePlugin.java b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/plugin/PistonQueuePlugin.java index 5d45b73..3e22a13 100644 --- a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/plugin/PistonQueuePlugin.java +++ b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/plugin/PistonQueuePlugin.java @@ -85,7 +85,7 @@ default void scheduleTasks(QueueListenerShared queueListener) { final QueueGroup defaultGroup = resolvedDefaultGroup; // Sends the position message and updates tab on an interval in chat schedule(() -> { - boolean targetsOnline = defaultGroup.targetServers().stream().anyMatch(queueListener.getOnlineServers()::contains); + boolean targetsOnline = defaultGroup.targetServers().stream().anyMatch(queueListener.getServerStatusManager().getOnlineServers()::contains); if (targetsOnline) { for (QueueType type : config.getAllQueueTypes()) { if (config.positionMessageChat()) { @@ -126,16 +126,16 @@ default void scheduleTasks(QueueListenerShared queueListener) { List servers = new ArrayList<>(config.kickWhenDownServers()); CountDownLatch latch = new CountDownLatch(servers.size()); for (String server : servers) { - CompletableFuture future = CompletableFuture.runAsync(() -> { + CompletableFuture.runAsync(() -> { try { Optional serverInfoWrapper = getServer(server); if (serverInfoWrapper.isPresent()) { if (serverInfoWrapper.get().isOnline()) { - queueListener.getOnlineServers().add(server); + queueListener.getServerStatusManager().online(server); } else { warning("Server %s is down!!!".formatted(server)); - queueListener.getOnlineServers().remove(server); + queueListener.getServerStatusManager().offline(server); } } else { warning("Server \"%s\" not set up!!! Check out: https://github.com/AlexProgrammerDE/PistonQueue/wiki/FAQ#server-not-set-up-error".formatted(server)); @@ -143,8 +143,7 @@ default void scheduleTasks(QueueListenerShared queueListener) { } finally { latch.countDown(); } - }); - future.exceptionally(ex -> { + }).exceptionally(ex -> { error("Failed to check status of server " + server + ": " + ex.getMessage()); return null; }); diff --git a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/QueueListenerShared.java b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/QueueListenerShared.java index c67c12a..9736ec6 100644 --- a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/QueueListenerShared.java +++ b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/QueueListenerShared.java @@ -47,7 +47,7 @@ public abstract class QueueListenerShared { private final PistonQueuePlugin plugin; @Getter - private final Set onlineServers = ConcurrentHashMap.newKeySet(); + private final ServerStatusManager serverStatusManager; private final QueueEnvironment queueEnvironment; private final QueuePlacementCoordinator queuePlacementCoordinator; private final QueueMoveProcessor queueMoveProcessor; @@ -57,8 +57,9 @@ public abstract class QueueListenerShared { protected QueueListenerShared(PistonQueuePlugin plugin) { this.plugin = plugin; - this.queueEnvironment = new QueueEnvironment(plugin, this::currentConfig, onlineServers); Config config = currentConfig(); + this.serverStatusManager = new ServerStatusManager(this::currentConfig); + this.queueEnvironment = new QueueEnvironment(plugin, this::currentConfig, serverStatusManager::getOnlineServers); this.usernameValidator = new UsernameValidator(config); this.shadowBanKickHandler = new ShadowBanKickHandler(config); diff --git a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/ServerStatusManager.java b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/ServerStatusManager.java new file mode 100644 index 0000000..fc7d75a --- /dev/null +++ b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/ServerStatusManager.java @@ -0,0 +1,46 @@ +package net.pistonmaster.pistonqueue.shared.queue; + +import net.pistonmaster.pistonqueue.shared.config.Config; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +public class ServerStatusManager { + private final Supplier configSupplier; + + private final Map onlinePingCounts = new ConcurrentHashMap<>(); + + public ServerStatusManager(Supplier configSupplier) { + this.configSupplier = configSupplier; + } + + public void online(String server) { + onlinePingCounts.merge(server, 1, (oldValue, newValue) -> { + //this prevents overflows, count never goes over the configured amount + final int sum = Integer.sum(oldValue, newValue); + if (sum > configSupplier.get().minOnlineChecks()) { + return oldValue; + } + return sum; + }); + } + + public void offline(String server) { + onlinePingCounts.remove(server); + } + + public Set getOnlineServers() { + return onlinePingCounts.entrySet().stream() + .filter(entry -> entry.getValue() >= configSupplier.get().minOnlineChecks()) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + } + + // For testing purposes so we can assert there is no overflow risk + public int getOnlinePingCount(String server) { + return onlinePingCounts.getOrDefault(server, 0); + } +} diff --git a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEnvironment.java b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEnvironment.java index 310deaa..61c9af6 100644 --- a/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEnvironment.java +++ b/shared/src/main/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEnvironment.java @@ -21,9 +21,9 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import net.pistonmaster.pistonqueue.shared.config.Config; +import net.pistonmaster.pistonqueue.shared.plugin.PistonQueuePlugin; import net.pistonmaster.pistonqueue.shared.queue.QueueGroup; import net.pistonmaster.pistonqueue.shared.queue.QueueType; -import net.pistonmaster.pistonqueue.shared.plugin.PistonQueuePlugin; import java.util.List; import java.util.Objects; @@ -35,12 +35,12 @@ public final class QueueEnvironment { private final PistonQueuePlugin plugin; private final Supplier configSupplier; - private final Set onlineServers; + private final Supplier> onlineServersSupplier; - public QueueEnvironment(PistonQueuePlugin plugin, Supplier configSupplier, Set onlineServers) { + public QueueEnvironment(PistonQueuePlugin plugin, Supplier configSupplier, Supplier> onlineServersSupplier) { this.plugin = Objects.requireNonNull(plugin, "plugin"); this.configSupplier = Objects.requireNonNull(configSupplier, "configSupplier"); - this.onlineServers = Objects.requireNonNull(onlineServers, "onlineServers"); + this.onlineServersSupplier = Objects.requireNonNull(onlineServersSupplier, "onlineServersSupplier"); } @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Plugin API is immutable for consumers") @@ -52,9 +52,8 @@ public Config config() { return configSupplier.get(); } - @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "Caller needs live view for synchronization") public Set onlineServers() { - return onlineServers; + return onlineServersSupplier.get(); } public QueueGroup defaultGroup() { @@ -94,7 +93,7 @@ public String defaultTarget(QueueGroup group) { } public boolean isGroupTargetOnline(QueueGroup group) { - return group.targetServers().stream().anyMatch(onlineServers::contains); + return group.targetServers().stream().anyMatch(onlineServers()::contains); } /// Checks if at least one queue server in the group is online. @@ -102,6 +101,6 @@ public boolean isGroupTargetOnline(QueueGroup group) { /// @param group the queue group to check /// @return true if at least one queue server is online public boolean isGroupQueueServerOnline(QueueGroup group) { - return group.queueServers().stream().anyMatch(onlineServers::contains); + return group.queueServers().stream().anyMatch(onlineServers()::contains); } } diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/KickEventHandlerTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/KickEventHandlerTest.java index d59565a..6400395 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/KickEventHandlerTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/KickEventHandlerTest.java @@ -41,7 +41,7 @@ void redirectsToQueueWhenKickedFromDownTargetServer() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -65,7 +65,7 @@ void doesNotRedirectWhenQueueRedirectionDisabled() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -87,7 +87,7 @@ void doesNotRedirectWhenKickedFromNonTargetServer() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -109,7 +109,7 @@ void doesNotRedirectWhenKickReasonDoesNotMatch() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -130,7 +130,7 @@ void setsCustomKickMessageWhenEnabledAndWillDisconnect() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -151,7 +151,7 @@ void doesNotSetKickMessageWhenDisabled() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -172,7 +172,7 @@ void doesNotSetKickMessageWhenNotDisconnecting() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -194,7 +194,7 @@ void handlesKickWithoutReason() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); @@ -217,7 +217,7 @@ void caseInsensitiveKickReasonMatching() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); KickEventHandler handler = new KickEventHandler(config, environment, selector); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueCleanerTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueCleanerTest.java index 8e62141..c06039b 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueCleanerTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueCleanerTest.java @@ -37,7 +37,7 @@ void removesStaleEntriesWhenPlayerDisconnected() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueCleaner cleaner = new QueueCleaner(environment); QueueType type = QueueTestUtils.defaultQueueType(config); @@ -56,7 +56,7 @@ void keepsActiveQueueEntries() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueCleaner cleaner = new QueueCleaner(environment); QueueType type = QueueTestUtils.defaultQueueType(config); @@ -76,7 +76,7 @@ void handlesEmptyQueue() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueCleaner cleaner = new QueueCleaner(environment); cleaner.cleanGroup(group); @@ -90,7 +90,7 @@ void removesMultipleStaleEntries() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueCleaner cleaner = new QueueCleaner(environment); QueueType type = QueueTestUtils.defaultQueueType(config); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueConnectorTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueConnectorTest.java index ab878e7..bd98e60 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueConnectorTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueConnectorTest.java @@ -36,7 +36,7 @@ void calculateEffectiveFreeSlotsReturnsZeroWhenNoSlots() { Config config = QueueTestUtils.createConfigWithSingleQueueType(5); QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); Set shadowBannedNames = ConcurrentHashMap.newKeySet(); ShadowBanService shadowBanService = shadowBannedNames::contains; @@ -56,7 +56,7 @@ void calculateEffectiveFreeSlotsRespectsMaxPlayersPerMove() { config.setMaxPlayersPerMove(2); QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); Set shadowBannedNames = ConcurrentHashMap.newKeySet(); ShadowBanService shadowBanService = shadowBannedNames::contains; @@ -76,7 +76,7 @@ void shouldSkipPlayerDueToShadowBanReturnsTrueForLoopBan() { config.setShadowBanType(BanType.LOOP); QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); Set shadowBannedNames = ConcurrentHashMap.newKeySet(); shadowBannedNames.add("BannedPlayer"); @@ -96,7 +96,7 @@ void shouldSkipPlayerDueToShadowBanReturnsFalseForNonBannedPlayer() { config.setShadowBanType(BanType.LOOP); QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); Set shadowBannedNames = ConcurrentHashMap.newKeySet(); ShadowBanService shadowBanService = shadowBannedNames::contains; @@ -114,7 +114,7 @@ void preparePlayerForConnectionSendsMessagesAndResetsList() { Config config = QueueTestUtils.createConfigWithSingleQueueType(5); QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); Set onlineServers = QueueTestUtils.onlineServers("queue", "target"); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); Set shadowBannedNames = ConcurrentHashMap.newKeySet(); ShadowBanService shadowBanService = shadowBannedNames::contains; diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEntryFactoryTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEntryFactoryTest.java index e1a57fe..db01b5b 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEntryFactoryTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueEntryFactoryTest.java @@ -37,7 +37,7 @@ void enqueuesPlayerWithCorrectTarget() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); @@ -63,7 +63,7 @@ void forcesDefaultTargetWhenConfigured() { for (String s : group.queueServers()) servers[i++] = s; for (String s : group.targetServers()) servers[i++] = s; Set onlineServers = QueueTestUtils.onlineServers(servers); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); @@ -82,7 +82,7 @@ void sendsFullMessageOnlyOnce() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); @@ -105,7 +105,7 @@ void setsPlayerListHeaderAndFooter() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); @@ -127,7 +127,7 @@ void doesNotSendFullMessageWhenNotServerFull() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueMoveProcessorTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueMoveProcessorTest.java index 886b8da..4fa56da 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueMoveProcessorTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueMoveProcessorTest.java @@ -254,7 +254,7 @@ private MoveContext context(int slots) { servers.addAll(group.queueServers()); servers.addAll(group.targetServers()); Set online = QueueTestUtils.onlineServers(servers.toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, online); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> online); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); QueueCleaner cleaner = new QueueCleaner(environment); QueueRecoveryHandler recovery = new QueueRecoveryHandler(environment); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueuePlacementCoordinatorTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueuePlacementCoordinatorTest.java index f6ee6f7..a9c3151 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueuePlacementCoordinatorTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueuePlacementCoordinatorTest.java @@ -240,7 +240,7 @@ void updatesPlayerListWithConfiguredHeader() { private CoordinatorContext context(Config config, Set onlineServers) { TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueAvailabilityCalculator calculator = new QueueAvailabilityCalculator(); QueueServerSelector selector = new QueueServerSelector(environment); QueueEntryFactory entryFactory = new QueueEntryFactory(environment, selector); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueRecoveryHandlerTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueRecoveryHandlerTest.java index 9f59c95..4410c49 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueRecoveryHandlerTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueRecoveryHandlerTest.java @@ -46,7 +46,7 @@ void recoversPlayerOnQueueServer() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = serversFromGroup(group); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueRecoveryHandler recoveryHandler = new QueueRecoveryHandler(environment); QueueType type = QueueTestUtils.defaultQueueType(config); @@ -65,7 +65,7 @@ void doesNotRecoverPlayerNotOnQueueServer() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueRecoveryHandler recoveryHandler = new QueueRecoveryHandler(environment); QueueType type = QueueTestUtils.defaultQueueType(config); @@ -84,7 +84,7 @@ void doesNotRecoverPlayerAlreadyInActiveTransfer() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = QueueTestUtils.onlineServers(group.queueServers().toArray(String[]::new)); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueRecoveryHandler recoveryHandler = new QueueRecoveryHandler(environment); QueueType type = QueueTestUtils.defaultQueueType(config); @@ -103,7 +103,7 @@ void doesNotDuplicateRecoveryEntries() { QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); QueueGroup group = QueueTestUtils.defaultGroup(config); Set onlineServers = serversFromGroup(group); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, onlineServers); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, () -> onlineServers); QueueRecoveryHandler recoveryHandler = new QueueRecoveryHandler(environment); QueueType type = QueueTestUtils.defaultQueueType(config); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueServerSelectorTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueServerSelectorTest.java index 2e6559f..85c6b62 100644 --- a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueServerSelectorTest.java +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/QueueServerSelectorTest.java @@ -40,7 +40,7 @@ class QueueServerSelectorTest { void throwsWhenNoQueueServersConfigured() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup emptyGroup = new QueueGroup("empty", List.of(), List.of("main"), List.of(), List.of()); @@ -52,7 +52,7 @@ void throwsWhenNoQueueServersConfigured() { void returnsSingleServerWhenOnlyOneConfigured() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup singleServerGroup = new QueueGroup("single", List.of("queue1"), List.of("main"), List.of(), List.of()); @@ -67,7 +67,7 @@ void roundRobinDistributesEvenly() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.ROUND_ROBIN); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup group = new QueueGroup("multi", List.of("queue1", "queue2", "queue3"), List.of("main"), List.of(), List.of()); @@ -89,7 +89,7 @@ void roundRobinCyclesCorrectly() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.ROUND_ROBIN); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup group = new QueueGroup("multi", List.of("queue1", "queue2"), List.of("main"), List.of(), List.of()); @@ -105,7 +105,7 @@ void leastPlayersSelectsServerWithFewestPlayers() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.LEAST_PLAYERS); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); // Register servers with different player counts @@ -131,7 +131,7 @@ void leastPlayersSelectsFirstServerOnTie() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.LEAST_PLAYERS); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); // Register servers with same player count (0) - just register, we don't need the return values @@ -152,7 +152,7 @@ void leastPlayersTreatsOfflineServerAsFullest() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.LEAST_PLAYERS); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); // Only register queue2, so queue1 and queue3 are "offline" (not found) @@ -172,7 +172,7 @@ void randomSelectsFromAllServers() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.RANDOM); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup group = new QueueGroup("multi", List.of("queue1", "queue2", "queue3"), List.of("main"), List.of(), List.of()); @@ -194,7 +194,7 @@ void roundRobinHandlesCounterWrapAround() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.ROUND_ROBIN); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); QueueGroup group = new QueueGroup("multi", List.of("queue1", "queue2"), List.of("main"), List.of(), List.of()); @@ -211,7 +211,7 @@ void selectsCorrectlyAfterStrategyChange() { Config config = QueueTestUtils.createConfigWithSingleQueueType(10); config.setQueueLoadBalancing(LoadBalancingStrategy.ROUND_ROBIN); TestQueuePlugin plugin = new TestQueuePlugin(config); - QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set.of()); + QueueEnvironment environment = new QueueEnvironment(plugin, plugin::getConfiguration, Set::of); QueueServerSelector selector = new QueueServerSelector(environment); TestServer queue1 = plugin.registerServer("queue1"); diff --git a/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/ServerStatusManagerTest.java b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/ServerStatusManagerTest.java new file mode 100644 index 0000000..286f082 --- /dev/null +++ b/shared/src/test/java/net/pistonmaster/pistonqueue/shared/queue/logic/ServerStatusManagerTest.java @@ -0,0 +1,104 @@ +package net.pistonmaster.pistonqueue.shared.queue.logic; + +import net.pistonmaster.pistonqueue.shared.config.Config; +import net.pistonmaster.pistonqueue.shared.queue.ServerStatusManager; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ServerStatusManagerTest { + + @Test + void onlyOnlineAfterConfiguredCount() { + Config config = QueueTestUtils.createConfigWithSingleQueueType(5); + config.setMinOnlineChecks(3); + + QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); + ServerStatusManager serverStatusManager = new ServerStatusManager(plugin::getConfiguration); + + //first time, should not be online + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().isEmpty()); + assertEquals(1, serverStatusManager.getOnlinePingCount("testServer")); + + //second time, should not be online + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().isEmpty()); + assertEquals(2, serverStatusManager.getOnlinePingCount("testServer")); + + //third time, should be online + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + assertEquals(3, serverStatusManager.getOnlinePingCount("testServer")); + + //fourth time, should still be online, but count should not be over our limit (3) + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + assertEquals(3, serverStatusManager.getOnlinePingCount("testServer")); + } + + @Test + void offlineAfterOneTime() { + Config config = QueueTestUtils.createConfigWithSingleQueueType(5); + config.setMinOnlineChecks(3); + + QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); + ServerStatusManager serverStatusManager = new ServerStatusManager(plugin::getConfiguration); + + //call online three times to make it online + serverStatusManager.online("testServer"); + serverStatusManager.online("testServer"); + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + + //now call offline once, should be offline now + serverStatusManager.offline("testServer"); + assertTrue(serverStatusManager.getOnlineServers().isEmpty()); + } + + @Test + void onlineWithZeroMinChecks() { + Config config = QueueTestUtils.createConfigWithSingleQueueType(5); + config.setMinOnlineChecks(0); + + QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); + ServerStatusManager serverStatusManager = new ServerStatusManager(plugin::getConfiguration); + + //call online once to make it online + serverStatusManager.online("testServer"); + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + } + + @Test + void onlineWithZeroMinChecksOverflow() { + Config config = QueueTestUtils.createConfigWithSingleQueueType(5); + config.setMinOnlineChecks(0); + + QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); + ServerStatusManager serverStatusManager = new ServerStatusManager(plugin::getConfiguration); + + //call online 10 times, should still be online and count should be 1 + for (int i = 0; i < 10; i++) { + serverStatusManager.online("testServer"); + } + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + assertEquals(1, serverStatusManager.getOnlinePingCount("testServer")); + } + + @Test + void onlineWithNegativeMinChecks() { + Config config = QueueTestUtils.createConfigWithSingleQueueType(5); + config.setMinOnlineChecks(-1); + + QueueTestUtils.TestQueuePlugin plugin = new QueueTestUtils.TestQueuePlugin(config); + ServerStatusManager serverStatusManager = new ServerStatusManager(plugin::getConfiguration); + + //call online 10 times, should still be online and count should be 1 + for (int i = 0; i < 10; i++) { + serverStatusManager.online("testServer"); + } + assertTrue(serverStatusManager.getOnlineServers().contains("testServer")); + assertEquals(1, serverStatusManager.getOnlinePingCount("testServer")); + } +}