From fbaa6c68f954274562b700f389c079098afdf26b Mon Sep 17 00:00:00 2001 From: Jules Date: Fri, 17 Oct 2025 23:27:32 +0200 Subject: [PATCH] Player data load queues to avoid SQL bursting --- .../java/net/Indyuce/mmocore/MMOCore.java | 11 +++--- .../mmocore/admin/ExportDataTreeNode.java | 9 +++-- .../mmocore/admin/SaveDataTreeNode.java | 2 +- .../manager/data/PlayerDataManager.java | 3 +- .../data/sql/PlayerDataTableUpdater.java | 34 +++++-------------- ...LDataHandler.java => SQLDatabaseImpl.java} | 33 +++++++----------- ...DataHandler.java => YAMLDatabaseImpl.java} | 9 +++-- MMOCore-Dist/src/main/resources/config.yml | 2 ++ 8 files changed, 37 insertions(+), 66 deletions(-) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/{SQLDataHandler.java => SQLDatabaseImpl.java} (92%) rename MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/yaml/{YAMLPlayerDataHandler.java => YAMLDatabaseImpl.java} (97%) diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java index 6b8895ca..8052c9c0 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/MMOCore.java @@ -3,7 +3,6 @@ package net.Indyuce.mmocore; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.data.SynchronizedDataManager; -import io.lumine.mythic.lib.data.sql.SQLDataSource; import io.lumine.mythic.lib.metrics.bukkit.Metrics; import io.lumine.mythic.lib.module.MMOPlugin; import io.lumine.mythic.lib.player.modifier.PlayerModifier; @@ -12,8 +11,8 @@ import io.lumine.mythic.lib.version.SpigotPlugin; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.api.player.attribute.AttributeModifier; import net.Indyuce.mmocore.api.player.profess.resource.PlayerResource; -import net.Indyuce.mmocore.command.builtin.mmocore.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.command.ToggleableCommand; +import net.Indyuce.mmocore.command.builtin.mmocore.MMOCoreCommandTreeRoot; import net.Indyuce.mmocore.comp.citizens.CitizenInteractEventListener; import net.Indyuce.mmocore.comp.citizens.CitizensMMOLoader; import net.Indyuce.mmocore.comp.mythicmobs.MythicHook; @@ -39,7 +38,8 @@ import net.Indyuce.mmocore.manager.data.DataProvider; import net.Indyuce.mmocore.manager.data.GuildDataManager; import net.Indyuce.mmocore.manager.data.LegacyDataProvider; import net.Indyuce.mmocore.manager.data.PlayerDataManager; -import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; +import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl; +import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl; import net.Indyuce.mmocore.manager.profession.*; import net.Indyuce.mmocore.manager.social.BoosterManager; import net.Indyuce.mmocore.manager.social.PartyManager; @@ -152,10 +152,7 @@ public class MMOCore extends MMOPlugin { getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); } - if (getConfig().isConfigurationSection("mysql") && getConfig().getBoolean("mysql.enabled")) { - final SQLDataSource dataSource = new SQLDataSource(this); - playerDataManager.setDataHandler(new SQLDataHandler(dataSource)); - } + playerDataManager.setupDatabase(SQLDatabaseImpl::new, YAMLDatabaseImpl::new); if (getConfig().isConfigurationSection("default-playerdata")) playerDataManager.loadDefaultData(getConfig().getConfigurationSection("default-playerdata")); diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java index 231555e6..4d1f1503 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/ExportDataTreeNode.java @@ -3,10 +3,9 @@ package net.Indyuce.mmocore.command.builtin.mmocore.admin; import io.lumine.mythic.lib.command.CommandTreeExplorer; import io.lumine.mythic.lib.command.CommandTreeNode; import io.lumine.mythic.lib.data.DataExport; -import io.lumine.mythic.lib.data.sql.SQLDataSource; import net.Indyuce.mmocore.MMOCore; -import net.Indyuce.mmocore.manager.data.sql.SQLDataHandler; -import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler; +import net.Indyuce.mmocore.manager.data.sql.SQLDatabaseImpl; +import net.Indyuce.mmocore.manager.data.yaml.YAMLDatabaseImpl; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -25,8 +24,8 @@ public class ExportDataTreeNode extends CommandTreeNode { // Export YAML to SQL final boolean result = new DataExport<>(MMOCore.plugin.playerDataManager, sender).start( - () -> new YAMLPlayerDataHandler(MMOCore.plugin), - () -> new SQLDataHandler(new SQLDataSource(MMOCore.plugin))); + YAMLDatabaseImpl::new, + SQLDatabaseImpl::new); return result ? CommandResult.SUCCESS : CommandResult.FAILURE; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java index a535d022..aca0772d 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/command/builtin/mmocore/admin/SaveDataTreeNode.java @@ -32,7 +32,7 @@ public class SaveDataTreeNode extends CommandTreeNode { return CommandResult.FAILURE; } - MMOCore.plugin.playerDataManager.getDataHandler().saveData(PlayerData.get(player), SaveReason.AUTOSAVE); + MMOCore.plugin.playerDataManager.saveData(PlayerData.get(player), SaveReason.AUTOSAVE); return CommandResult.SUCCESS; } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java index 550845b9..a82fe222 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/PlayerDataManager.java @@ -7,7 +7,6 @@ import net.Indyuce.mmocore.MMOCore; import net.Indyuce.mmocore.api.event.PlayerLevelChangeEvent; import net.Indyuce.mmocore.api.player.PlayerData; import net.Indyuce.mmocore.comp.profile.MMOCoreProfileDataModule; -import net.Indyuce.mmocore.manager.data.yaml.YAMLPlayerDataHandler; import net.Indyuce.mmocore.player.DefaultPlayerData; import org.bukkit.configuration.ConfigurationSection; import org.jetbrains.annotations.NotNull; @@ -16,7 +15,7 @@ public class PlayerDataManager extends SynchronizedDataManager requestMap = new HashMap<>(); - public PlayerDataTableUpdater(SQLDataSource provider, PlayerData playerData) { + public PlayerDataTableUpdater(SQLDatabaseImpl provider, PlayerData playerData) { this.playerData = playerData; this.provider = provider; this.effectiveId = playerData.getEffectiveId(); } public void executeRequest(@NotNull SaveReason saveReason) { - final String request = "INSERT INTO " + SQLDataHandler.DATA_TABLE_NAME + "(" + SQLDataHandler.UUID_FIELD_NAME + ", " + formatCollection(requestMap.keySet(), false) + final String request = "INSERT INTO " + provider.getUserDataTableName() + "(" + SQLDatabaseImpl.UUID_FIELD_NAME + ", " + formatCollection(requestMap.keySet(), false) + ") VALUES('" + effectiveId + "'," + formatCollection(requestMap.values(), true) + ")" + " ON DUPLICATE KEY UPDATE " + formatMap() + ";"; - try { - final Connection connection = provider.getConnection(); - try { - final PreparedStatement statement = connection.prepareStatement(request); - try { - statement.executeUpdate(); - } catch (SQLException exception) { - MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead"); - new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason); - exception.printStackTrace(); - } finally { - statement.close(); - } - } catch (SQLException exception) { - MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead"); - new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason); - exception.printStackTrace(); - } finally { - connection.close(); - } + try (Connection connection = provider.getConnection()) { + final PreparedStatement statement = connection.prepareStatement(request); + statement.executeUpdate(); } catch (SQLException exception) { MMOCore.log(Level.WARNING, "Could not save player data of " + effectiveId + ", saving through YAML instead"); - new YAMLPlayerDataHandler(MMOCore.plugin).saveData(playerData, saveReason); + new YAMLDatabaseImpl().saveData(playerData, saveReason); exception.printStackTrace(); } } diff --git a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java similarity index 92% rename from MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java rename to MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java index 65679ec5..af686973 100644 --- a/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDataHandler.java +++ b/MMOCore-API/src/main/java/net/Indyuce/mmocore/manager/data/sql/SQLDatabaseImpl.java @@ -4,8 +4,7 @@ import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.data.DataLoadResult; import io.lumine.mythic.lib.data.SaveReason; -import io.lumine.mythic.lib.data.sql.SQLDataSource; -import io.lumine.mythic.lib.data.sql.SQLSynchronizedDataHandler; +import io.lumine.mythic.lib.data.sql.SQLDatabase; import io.lumine.mythic.lib.gson.JsonArray; import io.lumine.mythic.lib.gson.JsonElement; import io.lumine.mythic.lib.gson.JsonObject; @@ -33,12 +32,11 @@ import java.util.UUID; import java.util.logging.Level; import java.util.stream.Collectors; -public class SQLDataHandler extends SQLSynchronizedDataHandler { - public static final String DATA_TABLE_NAME = "mmocore_playerdata"; +public class SQLDatabaseImpl extends SQLDatabase { public static final String UUID_FIELD_NAME = "uuid"; - public SQLDataHandler(SQLDataSource dataSource) { - super(dataSource, DATA_TABLE_NAME, UUID_FIELD_NAME); + public SQLDatabaseImpl() { + super(MMOCore.plugin, UUID_FIELD_NAME); } private static final String[] NEW_COLUMNS = new String[]{ @@ -58,7 +56,7 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler { - try { - if (!result.next()) - getDataSource().executeUpdate("ALTER TABLE " + DATA_TABLE_NAME + " ADD COLUMN " + columnName + " " + dataType); - } catch (SQLException exception) { - exception.printStackTrace(); - } - }); + final var columnName = NEW_COLUMNS[i]; + final var dataType = NEW_COLUMNS[i + 1]; + executeQuery("SELECT * FROM `information_schema`.`COLUMNS` WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?", result -> { + if (!result.next()) + executeUpdate("ALTER TABLE " + userdataTableName + " ADD COLUMN " + columnName + " " + dataType); + }, databaseName, userdataTableName, columnName); } // Modify exp to be a double precision instead - getDataSource().executeUpdateAsync("ALTER TABLE " + DATA_TABLE_NAME + " MODIFY COLUMN experience DOUBLE PRECISION"); + executeUpdate("ALTER TABLE `" + userdataTableName + "` MODIFY COLUMN experience DOUBLE PRECISION"); } @Override @@ -207,7 +200,7 @@ public class SQLDataHandler extends SQLSynchronizedDataHandler { - public YAMLPlayerDataHandler(MMOPlugin owning) { - super(owning); +public class YAMLDatabaseImpl extends YAMLFlatDatabase { + public YAMLDatabaseImpl() { + super(MMOCore.plugin); } @Override diff --git a/MMOCore-Dist/src/main/resources/config.yml b/MMOCore-Dist/src/main/resources/config.yml index f29db55e..a1026055 100644 --- a/MMOCore-Dist/src/main/resources/config.yml +++ b/MMOCore-Dist/src/main/resources/config.yml @@ -26,6 +26,8 @@ mysql: prepStmtCacheSize: 250 prepStmtCacheSqlLimit: 2048 + userdata-table-name: 'mmocore_playerdata' + # The default values for all playerdata # All new players will start with these values default-playerdata: