Merge pull request #35 from SKBotNL/master

Database migrations and "total" field in PlayerShards
This commit was merged in pull request #35.
This commit is contained in:
NotAlexNoyle authored and GitHub committed 2026-04-04 12:22:37 -04:00
commit 65d5100486
8 files changed
+97 -88

No files matched your search

+7
View File
@@ -55,9 +55,16 @@ repositories {
dependencies {
compileOnly("org.purpurmc.purpur:purpur-api:1.19.4-R0.1-SNAPSHOT") // Declare Purpur API version to be packaged.
compileOnly("net.luckperms:api:5.5") // Import the LuckPerms API.
implementation("io.lettuce:lettuce-core:7.2.0.RELEASE") // Import the Lettuce API for keydb.
implementation("org.flywaydb:flyway-core:12.3.0")
implementation("org.flywaydb:flyway-database-postgresql:12.3.0")
implementation("org.postgresql:postgresql:42.7.9")
implementation("com.github.jasync-sql:jasync-postgresql:2.2.4") // Import the jasync Postgres API.
implementation("it.unimi.dsi:fastutil-core:8.5.16")
implementation("org.jetbrains.kotlin:kotlin-stdlib") // Import the Kotlin standard library.
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("org.slf4j:slf4j-api:2.0.17") // Bundle a relocated SLF4J API for shaded dependencies.
@@ -1,13 +1,10 @@
package net.trueog.diamondbankog
import java.sql.SQLException
import java.util.*
import net.trueog.diamondbankog.PostgreSQL.PlayerShards
import net.trueog.diamondbankog.PostgreSQL.ShardType
interface BalanceManager {
@Throws(SQLException::class, ClassNotFoundException::class) fun init()
suspend fun setPlayerShards(uuid: UUID, shards: Long, type: ShardType): Result<Unit>
suspend fun addToBankShards(uuid: UUID, shards: Long): Result<Unit>
@@ -0,0 +1,5 @@
package net.trueog.diamondbankog
interface BalanceManagerFactory {
fun create(): BalanceManager?
}
@@ -1,6 +1,5 @@
package net.trueog.diamondbankog
import java.sql.SQLException
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger
@@ -11,14 +10,17 @@ import net.trueog.diamondbankog.ErrorHandler.handleError
import net.trueog.diamondbankog.PostgreSQL.PlayerShards
import net.trueog.diamondbankog.PostgreSQL.ShardType
internal class CachingBalanceManager : BalanceManager {
internal class CachingBalanceManager private constructor() : BalanceManager {
val cache = Cache()
val postgreSQL = PostgreSQL()
lateinit var postgreSQL: PostgreSQL
val beingModified = ConcurrentHashMap<Pair<UUID, ShardType>, AtomicInteger>()
@Throws(SQLException::class, ClassNotFoundException::class)
override fun init() {
postgreSQL.initDB()
companion object : BalanceManagerFactory {
override fun create(): BalanceManager? {
val cachingBalanceManager = CachingBalanceManager()
cachingBalanceManager.postgreSQL = PostgreSQL.create() ?: return null
return cachingBalanceManager
}
}
private fun increment(uuid: UUID, type: ShardType) {
@@ -21,7 +21,7 @@ internal open class DiamondBankOG : JavaPlugin() {
lateinit var plugin: DiamondBankOG
lateinit var config: YamlConfig
lateinit var eventManager: EventManager
lateinit var balanceManager: CachingBalanceManager
lateinit var balanceManager: BalanceManager
lateinit var redis: Redis
lateinit var luckPerms: LuckPerms
@@ -59,14 +59,12 @@ internal open class DiamondBankOG : JavaPlugin() {
eventManager = EventManager()
balanceManager = CachingBalanceManager()
try {
balanceManager.init()
} catch (e: Exception) {
e.printStackTrace()
Bukkit.getPluginManager().disablePlugin(this)
return
}
balanceManager =
CachingBalanceManager.create()
?: run {
Bukkit.getPluginManager().disablePlugin(this)
return
}
redis = Redis()
if (redis.testConnection()) {
@@ -4,7 +4,6 @@ import com.github.jasync.sql.db.asSuspending
import com.github.jasync.sql.db.pool.ConnectionPool
import com.github.jasync.sql.db.postgresql.PostgreSQLConnection
import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder
import java.sql.SQLException
import java.util.*
import kotlinx.coroutines.future.await
import net.trueog.diamondbankog.DiamondBankException.*
@@ -12,8 +11,10 @@ import net.trueog.diamondbankog.DiamondBankOG.Companion.balanceManager
import net.trueog.diamondbankog.DiamondBankOG.Companion.config
import net.trueog.diamondbankog.DiamondBankOG.Companion.economyDisabled
import net.trueog.diamondbankog.DiamondBankOG.Companion.plugin
import org.flywaydb.core.Flyway
import org.postgresql.ds.PGSimpleDataSource
class PostgreSQL {
class PostgreSQL private constructor() {
lateinit var pool: ConnectionPool<PostgreSQLConnection>
class NoRowsException : Exception()
@@ -25,67 +26,34 @@ class PostgreSQL {
TOTAL("bank_shards, inventory_shards, ender_chest_shards"),
}
@Throws(SQLException::class, ClassNotFoundException::class)
fun initDB() {
try {
pool =
PostgreSQLConnectionBuilder.createConnectionPool(
"${config.postgresUrl}?user=${config.postgresUser}&password=${config.postgresPassword}"
)
val createTable =
pool.sendPreparedStatement(
"CREATE TABLE IF NOT EXISTS ${config.postgresTable}(uuid UUID PRIMARY KEY, bank_shards BIGINT DEFAULT 0, inventory_shards BIGINT DEFAULT 0, ender_chest_shards BIGINT DEFAULT 0, total_shards BIGINT GENERATED ALWAYS AS ( COALESCE(bank_shards, 0) + COALESCE(inventory_shards, 0) + COALESCE(ender_chest_shards, 0) ) STORED)"
)
createTable.join()
val createTotalShardsIndex =
pool.sendPreparedStatement(
"CREATE INDEX IF NOT EXISTS idx_total_shards ON ${config.postgresTable}(total_shards DESC)"
)
createTotalShardsIndex.join()
companion object {
fun create(): PostgreSQL? {
val postgreSQL = PostgreSQL()
val createLogTable =
pool.sendPreparedStatement(
"CREATE TABLE IF NOT EXISTS ${config.postgresLogTable}(id SERIAL PRIMARY KEY, player_uuid UUID NOT NULL, transferred_shards BIGINT NOT NULL, player_to_uuid UUID, transaction_reason TEXT, notes TEXT, timestamp TIMESTAMPTZ DEFAULT NOW())"
try {
val jdbcUrl = "${config.postgresUrl}?user=${config.postgresUser}&password=${config.postgresPassword}"
val pg = PGSimpleDataSource()
pg.setUrl(jdbcUrl)
val flyway = Flyway.configure(DiamondBankOG::class.java.classLoader).dataSource(pg).load()
flyway.migrate()
postgreSQL.pool = PostgreSQLConnectionBuilder.createConnectionPool(jdbcUrl)
return postgreSQL
} catch (e: Exception) {
economyDisabled = true
plugin.logger.severe(
"ECONOMY DISABLED! Something went wrong while trying to initialise PostgreSQL. Is PostgreSQL running? Are the PostgreSQL config variables correct?"
)
createLogTable.join()
// @formatter:off
val createFunction =
pool.sendPreparedStatement(
"CREATE OR REPLACE FUNCTION fifo_limit_trigger() RETURNS TRIGGER AS $$" +
"DECLARE " +
"max_rows CONSTANT BIGINT := ${config.postgresLogLimit};" +
"BEGIN " +
"DELETE FROM ${config.postgresLogTable} " +
"WHERE id <= (" +
"SELECT id FROM ${config.postgresLogTable} " +
"ORDER BY id DESC " +
"OFFSET max_rows LIMIT 1" +
");" +
"RETURN NEW;" +
"END;" +
"$$ LANGUAGE plpgsql;"
)
// @formatter:on
createFunction.join()
val createTrigger =
pool.sendPreparedStatement(
"CREATE OR REPLACE TRIGGER fifo_limit_trigger\n" +
"AFTER INSERT ON ${config.postgresLogTable}\n" +
"FOR EACH STATEMENT\n" +
"EXECUTE FUNCTION fifo_limit_trigger();"
)
createTrigger.join()
} catch (e: Exception) {
economyDisabled = true
plugin.logger.severe(
"ECONOMY DISABLED! Something went wrong while trying to initialise PostgreSQL. Is PostgreSQL running? Are the PostgreSQL config variables correct?"
)
e.printStackTrace()
return
e.printStackTrace()
return null
}
}
}
data class PlayerShards(val bank: Long, val inventory: Long, val enderChest: Long)
data class PlayerShards(val bank: Long, val inventory: Long, val enderChest: Long) {
val total = bank + inventory + enderChest
}
suspend fun setPlayerShards(uuid: UUID, shards: Long, type: ShardType): Result<Unit> {
if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException())
@@ -17,23 +17,25 @@ internal class DiamondBankReload : CommandExecutor {
YamlConfig.create()
?: run {
sender.sendMessage(
mm.deserialize("<red>Failed to reload the config. Check the console for more information.")
mm.deserialize(
"${config.prefix}<reset>: <red>Failed to reload the config. Check the console for more information."
)
)
Bukkit.getPluginManager().disablePlugin(plugin)
return true
}
balanceManager = CachingBalanceManager()
try {
balanceManager.init()
} catch (e: Exception) {
e.printStackTrace()
sender.sendMessage(
mm.deserialize("<red>Failed to reload the config. Check the console for more information.")
)
Bukkit.getPluginManager().disablePlugin(plugin)
return true
}
balanceManager =
CachingBalanceManager.create()
?: run {
sender.sendMessage(
mm.deserialize(
"${config.prefix}<reset>: <red>Failed to reload the config. Check the console for more information."
)
)
Bukkit.getPluginManager().disablePlugin(plugin)
return true
}
sender.sendMessage(mm.deserialize("${config.prefix}<reset>: <green>Successfully reloaded the config."))
return true
@@ -0,0 +1,30 @@
CREATE TABLE diamond(
uuid UUID PRIMARY KEY, bank_shards BIGINT DEFAULT 0, inventory_shards BIGINT DEFAULT 0, ender_chest_shards BIGINT DEFAULT 0,
total_shards BIGINT GENERATED ALWAYS AS ( COALESCE(bank_shards, 0) + COALESCE(inventory_shards, 0) + COALESCE(ender_chest_shards, 0) ) STORED
);
CREATE INDEX idx_total_shards ON diamond(total_shards DESC);
CREATE TABLE diamond_log(
id SERIAL PRIMARY KEY, player_uuid UUID NOT NULL, transferred_shards BIGINT NOT NULL, player_to_uuid UUID,
transaction_reason TEXT, notes TEXT, timestamp TIMESTAMPTZ DEFAULT NOW()
);
CREATE FUNCTION fifo_limit_trigger() RETURNS TRIGGER AS $$
DECLARE
max_rows CONSTANT BIGINT := 500;
BEGIN
DELETE FROM diamond_log
WHERE id <= (
SELECT id FROM diamond_log
ORDER BY id DESC
OFFSET max_rows LIMIT 1
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER fifo_limit_trigger
AFTER INSERT ON diamond_log
FOR EACH STATEMENT
EXECUTE FUNCTION fifo_limit_trigger();