From 5aeeafc0417c5bed44e5f35dfb219f482afb4684 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Wed, 16 Feb 2022 16:32:38 +0000 Subject: [PATCH] MySQL Data Changes: Keys are now registered on first read/write --- .../eco/core/data/keys/KeyRegistry.java | 11 +++ .../eco/core/data/keys/PersistentDataKey.java | 30 --------- .../internal/spigot/data/EcoKeyRegistry.kt | 6 +- .../spigot/data/storage/DataHandler.kt | 8 +-- .../spigot/data/storage/MySQLDataHandler.kt | 67 +++++++++---------- .../spigot/data/storage/YamlDataHandler.kt | 2 +- 6 files changed, 51 insertions(+), 73 deletions(-) diff --git a/eco-api/src/main/java/com/willfp/eco/core/data/keys/KeyRegistry.java b/eco-api/src/main/java/com/willfp/eco/core/data/keys/KeyRegistry.java index 3827eab1..4673ee01 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/data/keys/KeyRegistry.java +++ b/eco-api/src/main/java/com/willfp/eco/core/data/keys/KeyRegistry.java @@ -1,6 +1,8 @@ package com.willfp.eco.core.data.keys; +import org.bukkit.NamespacedKey; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -21,4 +23,13 @@ public interface KeyRegistry { * @return The keys. */ Set> getRegisteredKeys(); + + /** + * Get persistent data key from namespaced key. + * + * @param namespacedKey The key. + * @return The key, or null if not found. + */ + @Nullable + PersistentDataKey getKeyFrom(@NotNull NamespacedKey namespacedKey); } diff --git a/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKey.java b/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKey.java index 171098ba..e1937c3e 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKey.java +++ b/eco-api/src/main/java/com/willfp/eco/core/data/keys/PersistentDataKey.java @@ -29,11 +29,6 @@ public class PersistentDataKey { */ private final PersistentDataKeyType type; - /** - * If the key is for server data. - */ - private final boolean isServerKey; - /** * Create a new Persistent Data Key. * @@ -44,25 +39,9 @@ public class PersistentDataKey { public PersistentDataKey(@NotNull final NamespacedKey key, @NotNull final PersistentDataKeyType type, @NotNull final T defaultValue) { - this(key, type, defaultValue, false); - } - - /** - * Create a new Persistent Data Key. - * - * @param key The key. - * @param type The data type. - * @param defaultValue The default value. - * @param isServerKey If the key is for server data. - */ - public PersistentDataKey(@NotNull final NamespacedKey key, - @NotNull final PersistentDataKeyType type, - @NotNull final T defaultValue, - final boolean isServerKey) { this.key = key; this.defaultValue = defaultValue; this.type = type; - this.isServerKey = isServerKey; Eco.getHandler().getKeyRegistry().registerKey(this); } @@ -103,15 +82,6 @@ public class PersistentDataKey { return this.type; } - /** - * Get if the key is for server data. - * - * @return If server key. - */ - public boolean isServerKey() { - return isServerKey; - } - /** * Get all persistent data keys. * diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoKeyRegistry.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoKeyRegistry.kt index ed856251..5fed77c4 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoKeyRegistry.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/EcoKeyRegistry.kt @@ -43,4 +43,8 @@ class EcoKeyRegistry: KeyRegistry { else -> throw NullPointerException("Null value found!") } } -} \ No newline at end of file + + override fun getKeyFrom(namespacedKey: NamespacedKey): PersistentDataKey<*>? { + return registry[namespacedKey] + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt index 309c1a52..c923102d 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/DataHandler.kt @@ -11,15 +11,11 @@ interface DataHandler { fun saveAll(uuids: Iterable) - fun updateKeys() { - - } - fun savePlayer(uuid: UUID) { - saveKeysForPlayer(uuid, PersistentDataKey.values()) + saveKeysFor(uuid, PersistentDataKey.values()) } fun write(uuid: UUID, key: NamespacedKey, value: T) - fun saveKeysForPlayer(uuid: UUID, keys: Set>) + fun saveKeysFor(uuid: UUID, keys: Set>) fun read(uuid: UUID, key: NamespacedKey): T? } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt index 3fd15f60..a3a572ed 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/MySQLDataHandler.kt @@ -28,6 +28,7 @@ import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.update import java.util.UUID import java.util.concurrent.Callable +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executors @Suppress("UNCHECKED_CAST") @@ -39,13 +40,13 @@ class MySQLDataHandler( handler, UUIDTable("eco_players"), plugin - ) { !it.isServerKey } + ) private val serverHandler = ImplementedMySQLHandler( handler, UUIDTable("eco_server"), plugin - ) { it.isServerKey } + ) override fun saveAll(uuids: Iterable) { serverHandler.saveAll(uuids.filter { it == serverProfileUUID }) @@ -58,7 +59,7 @@ class MySQLDataHandler( } } - override fun saveKeysForPlayer(uuid: UUID, keys: Set>) { + override fun saveKeysFor(uuid: UUID, keys: Set>) { applyFor(uuid) { it.saveKeysForRow(uuid, keys) } @@ -70,11 +71,6 @@ class MySQLDataHandler( } } - override fun updateKeys() { - playerHandler.updateKeys() - serverHandler.updateKeys() - } - private inline fun applyFor(uuid: UUID, function: (ImplementedMySQLHandler) -> R): R { return if (uuid == serverProfileUUID) { function(serverHandler) @@ -88,12 +84,12 @@ class MySQLDataHandler( private class ImplementedMySQLHandler( private val handler: EcoProfileHandler, private val table: UUIDTable, - plugin: EcoPlugin, - private val validator: (PersistentDataKey<*>) -> Boolean + plugin: EcoPlugin ) { private val columns = mutableMapOf>() private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build() private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory) + private val registeredKeys = ConcurrentHashMap.newKeySet() init { val config = HikariConfig() @@ -108,7 +104,6 @@ private class ImplementedMySQLHandler( Database.connect(HikariDataSource(config)) - transaction { SchemaUtils.create(table) } @@ -125,25 +120,27 @@ private class ImplementedMySQLHandler( } } - fun updateKeys() { - transaction { - for (key in Eco.getHandler().keyRegistry.registeredKeys) { - if (validator(key)) { - registerColumn(key, table) - } - } + fun ensureKeyRegistration(key: NamespacedKey) { + if (registeredKeys.contains(key)) { + return + } + transaction { + val persistentKey = Eco.getHandler().keyRegistry.getKeyFrom(key)!! + + registerColumn(persistentKey, table) SchemaUtils.createMissingTablesAndColumns(table, withLogs = false) + registeredKeys.add(key) } } fun write(uuid: UUID, key: NamespacedKey, value: T) { - getRow(uuid) - writeAsserted(uuid, key, value) + getOrCreateRow(uuid) + doWrite(uuid, key, value) } - private fun writeAsserted(uuid: UUID, key: NamespacedKey, value: T) { - val column: Column = getColumn(key.toString()) as Column + private fun doWrite(uuid: UUID, key: NamespacedKey, value: T) { + val column: Column = getColumn(key) as Column executor.submit { transaction { @@ -169,12 +166,10 @@ private class ImplementedMySQLHandler( executor.submit { transaction { - getRow(uuid) + getOrCreateRow(uuid) for (key in keys) { - if (validator(key)) { - writeAsserted(uuid, key.key, profile.read(key)) - } + doWrite(uuid, key.key, profile.read(key)) } } } @@ -184,8 +179,8 @@ private class ImplementedMySQLHandler( val doRead = Callable { var value: T? = null transaction { - val player = getRow(uuid) - value = player[getColumn(key.toString())] as T? + val row = getOrCreateRow(uuid) + value = row[getColumn(key)] as T? } return@Callable value @@ -219,28 +214,30 @@ private class ImplementedMySQLHandler( } } - private fun getColumn(name: String): Column<*> { + private fun getColumn(key: NamespacedKey): Column<*> { + ensureKeyRegistration(key) + val name = key.toString() val cached = columns[name] if (cached != null) { return cached } columns[name] = table.columns.stream().filter { it.name == name }.findFirst().get() - return getColumn(name) + return getColumn(key) } - private fun getRow(uuid: UUID): ResultRow { - val player = transaction { + private fun getOrCreateRow(uuid: UUID): ResultRow { + val row = transaction { table.select { table.id eq uuid }.limit(1).singleOrNull() } - return if (player != null) { - player + return if (row != null) { + row } else { transaction { table.insert { it[id] = uuid } } - getRow(uuid) + getOrCreateRow(uuid) } } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt index f43a1993..851ab08b 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/data/storage/YamlDataHandler.kt @@ -27,7 +27,7 @@ class YamlDataHandler( save() } - override fun saveKeysForPlayer(uuid: UUID, keys: Set>) { + override fun saveKeysFor(uuid: UUID, keys: Set>) { val profile = handler.loadGenericProfile(uuid) for (key in keys) {