diff --git a/src/main/java/world/bentobox/bentobox/BentoBox.java b/src/main/java/world/bentobox/bentobox/BentoBox.java index ae2b2f6df..c27a7c441 100644 --- a/src/main/java/world/bentobox/bentobox/BentoBox.java +++ b/src/main/java/world/bentobox/bentobox/BentoBox.java @@ -91,6 +91,8 @@ public class BentoBox extends JavaPlugin { private BukkitTask blueprintLoadingTask; + private boolean shutdown; + @Override public void onEnable(){ if (!ServerCompatibility.getInstance().checkCompatibility().isCanLaunch()) { @@ -193,8 +195,8 @@ public class BentoBox extends JavaPlugin { flagsManager.registerListeners(); // Load metrics - metrics = new BStats(this); - metrics.registerMetrics(); + metrics = new BStats(this); + metrics.registerMetrics(); // Register Multiverse hook - MV loads AFTER BentoBox // Make sure all worlds are already registered to Multiverse. @@ -273,6 +275,8 @@ public class BentoBox extends JavaPlugin { if (islandsManager != null) { islandsManager.shutdown(); } + // Close all async database tasks + shutdown = true; } /** @@ -495,4 +499,13 @@ public class BentoBox extends JavaPlugin { public void reloadConfig() { loadSettings(); } + + /** + * Check if plug has shutdown. Used to close databases that are running async. + * @return true if plugin has shutdown + * @since 1.13.0 + */ + public boolean isShutdown() { + return shutdown; + } } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java index cb0f6bf8f..dd36e4197 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java @@ -74,15 +74,15 @@ public class AdminRangeSetCommand extends CompositeCommand { // Well, now it can be applied without taking any risks! island.setProtectionRange(range); - // Call Protection Range Change event. Does not support cancelling. + // Call Protection Range Change event. Does not support canceling. IslandEvent.builder() - .island(island) - .location(island.getCenter()) - .reason(IslandEvent.Reason.RANGE_CHANGE) - .involvedPlayer(targetUUID) - .admin(true) - .protectionRange(range, oldRange) - .build(); + .island(island) + .location(island.getCenter()) + .reason(IslandEvent.Reason.RANGE_CHANGE) + .involvedPlayer(targetUUID) + .admin(true) + .protectionRange(range, oldRange) + .build(); user.sendMessage("commands.admin.range.set.success", TextVariables.NUMBER, String.valueOf(range)); diff --git a/src/main/java/world/bentobox/bentobox/database/AbstractDatabaseHandler.java b/src/main/java/world/bentobox/bentobox/database/AbstractDatabaseHandler.java index 200c17113..3590c6a27 100644 --- a/src/main/java/world/bentobox/bentobox/database/AbstractDatabaseHandler.java +++ b/src/main/java/world/bentobox/bentobox/database/AbstractDatabaseHandler.java @@ -95,32 +95,30 @@ public abstract class AbstractDatabaseHandler { this.databaseConnector = databaseConnector; this.dataObject = type; + // Return if plugin disabled + if (!plugin.isEnabled()) return; // Run async queue processQueue = new ConcurrentLinkedQueue<>(); - if (plugin.isEnabled()) { - asyncSaveTask = Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { - // Loop continuously - while (!shutdown || !processQueue.isEmpty()) { - // This catches any databases that are not explicitly closed - if (!plugin.isEnabled()) { - shutdown = true; - } - while (!processQueue.isEmpty()) { - processQueue.poll().run(); - } - // Clear the queue and then sleep - try { - Thread.sleep(25); - } catch (InterruptedException e) { - plugin.logError("Thread sleep error " + e.getMessage()); - Thread.currentThread().interrupt(); - } + asyncSaveTask = Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + // Loop continuously + while (!shutdown || !processQueue.isEmpty()) { + while (!processQueue.isEmpty()) { + processQueue.poll().run(); } - // Cancel - asyncSaveTask.cancel(); - databaseConnector.closeConnection(dataObject); - }); - } + // Shutdown flag + shutdown = plugin.isShutdown(); + // Clear the queue and then sleep + try { + Thread.sleep(25); + } catch (InterruptedException e) { + plugin.logError("Thread sleep error " + e.getMessage()); + Thread.currentThread().interrupt(); + } + } + // Cancel + asyncSaveTask.cancel(); + databaseConnector.closeConnection(dataObject); + }); } protected AbstractDatabaseHandler() {} @@ -173,4 +171,5 @@ public abstract class AbstractDatabaseHandler { * @since 1.1 */ public abstract void deleteID(String uniqueId); + } diff --git a/src/test/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandlerTest.java b/src/test/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandlerTest.java index 8d7064fc3..0e162a45f 100644 --- a/src/test/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandlerTest.java +++ b/src/test/java/world/bentobox/bentobox/database/yaml/YamlDatabaseHandlerTest.java @@ -304,7 +304,7 @@ public class YamlDatabaseHandlerTest { Mockito.verify(scheduler).runTaskAsynchronously(Mockito.eq(plugin), registerLambdaCaptor.capture()); Runnable lamda = registerLambdaCaptor.getValue(); // Cannot run with true otherwise it'll infinite loop - when(plugin.isEnabled()).thenReturn(false); + when(plugin.isShutdown()).thenReturn(true); lamda.run(); Mockito.verify(task).cancel();