From c2b371b0df3b793c3f331cd83dd3b811bb22cb73 Mon Sep 17 00:00:00 2001 From: Sven Date: Thu, 17 Jul 2025 17:00:41 +0200 Subject: [PATCH 1/8] Enable fairness of the transaction lock to guarantee FIFO queues --- .../kotlin/net/trueog/diamondbankog/TransactionLock.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/TransactionLock.kt b/src/main/kotlin/net/trueog/diamondbankog/TransactionLock.kt index 8ec0599..fd56902 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/TransactionLock.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/TransactionLock.kt @@ -14,7 +14,7 @@ internal class TransactionLock { } fun withLock(uuid: UUID, block: () -> T): T { - val lock = locks.computeIfAbsent(uuid) { Semaphore(1) } + val lock = locks.computeIfAbsent(uuid) { Semaphore(1, true) } lock.acquire() try { return block() @@ -24,7 +24,7 @@ internal class TransactionLock { } suspend fun withLockSuspend(uuid: UUID, block: suspend () -> T): T { - val lock = locks.computeIfAbsent(uuid) { Semaphore(1) } + val lock = locks.computeIfAbsent(uuid) { Semaphore(1, true) } lock.acquire() try { return block() @@ -34,7 +34,7 @@ internal class TransactionLock { } fun tryWithLock(uuid: UUID, block: () -> T): LockResult { - val lock = locks.computeIfAbsent(uuid) { Semaphore(1) } + val lock = locks.computeIfAbsent(uuid) { Semaphore(1, true) } return if (lock.tryAcquire()) { try { return LockResult.Acquired(block()) @@ -47,7 +47,7 @@ internal class TransactionLock { } suspend fun tryWithLockSuspend(uuid: UUID, block: suspend () -> T): LockResult { - val lock = locks.computeIfAbsent(uuid) { Semaphore(1) } + val lock = locks.computeIfAbsent(uuid) { Semaphore(1, true) } return if (lock.tryAcquire()) { try { LockResult.Acquired(block()) -- 2.47.3 From 2078f51d2b85873a90d81d01d7e45ddff4aae3ed Mon Sep 17 00:00:00 2001 From: Sven Date: Sat, 19 Jul 2025 23:55:51 +0200 Subject: [PATCH 2/8] New API and lots of internal changes --- .../net/trueog/diamondbankog/AutoDeposit.kt | 3 +- .../diamondbankog/DiamondBankAPIJava.kt | 237 ++++++++--------- .../diamondbankog/DiamondBankAPIKotlin.kt | 119 ++++----- .../net/trueog/diamondbankog/ErrorHandler.kt | 6 +- .../kotlin/net/trueog/diamondbankog/Events.kt | 84 +++--- .../diamondbankog/InventoryExtensions.kt | 31 +-- .../net/trueog/diamondbankog/PostgreSQL.kt | 244 +++++++++--------- .../trueog/diamondbankog/WithdrawHelper.kt | 63 ++--- .../trueog/diamondbankog/commands/Balance.kt | 55 ++-- .../trueog/diamondbankog/commands/Deposit.kt | 26 +- .../net/trueog/diamondbankog/commands/Pay.kt | 28 +- .../diamondbankog/commands/SetBankBalance.kt | 12 +- .../trueog/diamondbankog/commands/Withdraw.kt | 40 ++- 13 files changed, 442 insertions(+), 506 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/AutoDeposit.kt b/src/main/kotlin/net/trueog/diamondbankog/AutoDeposit.kt index d010408..cba9abf 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/AutoDeposit.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/AutoDeposit.kt @@ -38,8 +38,7 @@ internal object AutoDeposit { DiamondBankOG.scope.launch { DiamondBankOG.transactionLock.withLockSuspend(player.uniqueId) { - val error = DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, shards, ShardType.BANK) - if (error) { + DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, shards, ShardType.BANK).getOrElse { handleError(player.uniqueId, shards, null) player.sendMessage( DiamondBankOG.mm.deserialize( diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index 38d8734..c127971 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -4,8 +4,8 @@ import java.util.* import java.util.concurrent.CompletableFuture import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.future.future +import kotlinx.coroutines.runBlocking import net.trueog.diamondbankog.ErrorHandler.handleError -import net.trueog.diamondbankog.PostgreSQL.PlayerShards import net.trueog.diamondbankog.PostgreSQL.ShardType import net.trueog.diamondbankog.TransactionLock.LockResult import org.bukkit.Bukkit @@ -13,7 +13,8 @@ import org.bukkit.Bukkit @OptIn(DelicateCoroutinesApi::class) class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { /** - * WARNING: blocking, if the player has a transaction lock applied this function will wait until its released + * WARNING: do not run on a thread where blocking is unacceptable WARNING: lock is blocking, if the player has a + * transaction lock applied this function will wait until its released * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log @@ -22,23 +23,15 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { */ @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) @Suppress("unused") - fun blockingAddToPlayerBankShards( - uuid: UUID, - shards: Int, - transactionReason: String, - notes: String?, - ): CompletableFuture { + fun blockingAddToPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { + return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val error = postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } } @@ -46,6 +39,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException @@ -58,28 +53,20 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { DiamondBankException.OtherException::class, ) @Suppress("unused") - fun addToPlayerBankShards( - uuid: UUID, - shards: Int, - transactionReason: String, - notes: String?, - ): CompletableFuture { + fun addToPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { + return runBlocking { when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val error = postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } } ) { is LockResult.Acquired -> { @@ -94,7 +81,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** - * WARNING: blocking, if the player has a transaction lock applied this function will wait until its released + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log @@ -103,24 +91,14 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { */ @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) @Suppress("unused") - fun blockingSubtractFromPlayerBankShards( - uuid: UUID, - shards: Int, - transactionReason: String, - notes: String?, - ): CompletableFuture { + fun blockingSubtractFromPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { + return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val error = postgreSQL.subtractFromPlayerShards(uuid, shards, ShardType.BANK) - if (error) { - throw DiamondBankException.OtherException - } + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } } @@ -128,6 +106,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException @@ -140,28 +120,20 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { DiamondBankException.OtherException::class, ) @Suppress("unused") - fun subtractFromPlayerBankShards( - uuid: UUID, - shards: Int, - transactionReason: String, - notes: String?, - ): CompletableFuture { + fun subtractFromPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { + return runBlocking { when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val error = postgreSQL.subtractFromPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } } ) { is LockResult.Acquired -> { @@ -176,54 +148,97 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** - * WARNING: blocking, if the player has a transaction lock applied this function will wait until its released + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws DiamondBankException.OtherException + * @throws java.lang.Exception + */ + @Suppress("unused") fun blockingGetBankShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.BANK) + + /** + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released + * + * @throws DiamondBankException.EconomyDisabledException + * @throws java.lang.Exception */ - @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) @Suppress("unused") - fun blockingGetPlayerShards(uuid: UUID, type: ShardType): CompletableFuture { + fun blockingGetInventoryShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.INVENTORY) + + /** + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released + * + * @throws DiamondBankException.EconomyDisabledException + * @throws java.lang.Exception + */ + @Suppress("unused") + fun blockingGetEnderChestShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) + + private fun blockingGetShardTypeShards(uuid: UUID, type: ShardType): Int { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { - DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val playerShards = postgreSQL.getPlayerShards(uuid, type) - if (playerShards.isNeededShardTypeNull(type)) { - throw DiamondBankException.OtherException + return runBlocking { + val result = + DiamondBankOG.transactionLock.withLockSuspend(uuid) { + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.ALL -> postgreSQL.getTotalShards(uuid) + } } - playerShards - } + result.exceptionOrNull()?.let { throw it } + result.getOrThrow() } } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws DiamondBankException.OtherException + * @throws java.lang.Exception */ - @Throws( - DiamondBankException.EconomyDisabledException::class, - DiamondBankException.TransactionsLockedException::class, - DiamondBankException.OtherException::class, - ) - @Suppress("unused") - fun getPlayerShards(uuid: UUID, type: ShardType): CompletableFuture { + @Suppress("unused") fun getBankShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.BANK) + + /** + * WARNING: do not run on a thread where blocking is unacceptable + * + * @throws DiamondBankException.EconomyDisabledException + * @throws DiamondBankException.TransactionsLockedException + * @throws java.lang.Exception + */ + @Suppress("unused") fun getInventoryShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.INVENTORY) + + /** + * WARNING: do not run on a thread where blocking is unacceptable + * + * @throws DiamondBankException.EconomyDisabledException + * @throws DiamondBankException.TransactionsLockedException + * @throws java.lang.Exception + */ + @Suppress("unused") fun getEnderChestShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + + private fun getShardTypeShards(uuid: UUID, type: ShardType): Int { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException - return DiamondBankOG.scope.future { + return runBlocking { when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val playerShards = postgreSQL.getPlayerShards(uuid, type) - if (playerShards.isNeededShardTypeNull(type)) { - throw DiamondBankException.OtherException + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.ALL -> postgreSQL.getTotalShards(uuid) } - playerShards } ) { is LockResult.Acquired -> { - result.result + result.result.exceptionOrNull()?.let { throw it } + result.result.getOrThrow() } LockResult.Failed -> { @@ -234,6 +249,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.OtherException */ @@ -252,7 +269,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** - * WARNING: blocking, if the player has a transaction lock applied this function will wait until its released + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log @@ -289,9 +307,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } } @@ -299,6 +315,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException @@ -338,11 +356,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } } ) { is LockResult.Acquired -> { @@ -357,7 +373,8 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } /** - * WARNING: blocking, if the player has a transaction lock applied this function will wait until its released + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log @@ -398,28 +415,21 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { throw DiamondBankException.OtherException } - val error = postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog( - payerUuid, - shards, - receiverUuid, - transactionReason, - notes, - ) - if (transactionLogError) { - handleError(payerUuid, shards, null, receiverUuid, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(payerUuid, shards, receiverUuid, transactionReason, notes) + .getOrElse { handleError(payerUuid, shards, null, receiverUuid, true) } } } } /** + * WARNING: do not run on a thread where blocking is unacceptable + * * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException @@ -463,23 +473,14 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { throw DiamondBankException.OtherException } - val error = postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) throw DiamondBankException.OtherException } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog( - payerUuid, - shards, - receiverUuid, - transactionReason, - notes, - ) - if (transactionLogError) { - handleError(payerUuid, shards, null, receiverUuid, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(payerUuid, shards, receiverUuid, transactionReason, notes) + .getOrElse { handleError(payerUuid, shards, null, receiverUuid, true) } } ) { is LockResult.Acquired -> { diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt index 47ba5d4..6f737d4 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt @@ -3,7 +3,6 @@ package net.trueog.diamondbankog import java.util.* import kotlinx.coroutines.DelicateCoroutinesApi import net.trueog.diamondbankog.ErrorHandler.handleError -import net.trueog.diamondbankog.PostgreSQL.PlayerShards import net.trueog.diamondbankog.PostgreSQL.ShardType import net.trueog.diamondbankog.TransactionLock.LockResult import org.bukkit.Bukkit @@ -25,14 +24,11 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { ): Result { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val error = postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { return@withLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } @@ -56,16 +52,13 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val error = postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } Result.success(Unit) } @@ -96,14 +89,11 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val error = postgreSQL.subtractFromPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { return@withLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } @@ -127,16 +117,13 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val error = postgreSQL.subtractFromPlayerShards(uuid, shards, ShardType.BANK) - if (error) { + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } Result.success(Unit) } @@ -153,31 +140,49 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { /** WARNING: blocking, if the player has a transaction lock applied this function will wait until its released */ @Suppress("unused") - suspend fun blockingGetPlayerShards(uuid: UUID, type: ShardType): Result { + suspend fun blockingGetBankShards(uuid: UUID): Result = blockingGetShardTypeShards(uuid, ShardType.BANK) + + /** WARNING: blocking, if the player has a transaction lock applied this function will wait until its released */ + @Suppress("unused") + suspend fun blockingGetInventoryShards(uuid: UUID): Result = + blockingGetShardTypeShards(uuid, ShardType.INVENTORY) + + /** WARNING: blocking, if the player has a transaction lock applied this function will wait until its released */ + @Suppress("unused") + suspend fun blockingGetEnderChestShards(uuid: UUID): Result = + blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) + + private suspend fun blockingGetShardTypeShards(uuid: UUID, type: ShardType): Result { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val playerShards = postgreSQL.getPlayerShards(uuid, type) - if (playerShards.isNeededShardTypeNull(type)) { - return@withLockSuspend Result.failure(DiamondBankException.OtherException) + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.ALL -> postgreSQL.getTotalShards(uuid) } - - Result.success(playerShards) } } - @Suppress("unused") - suspend fun getPlayerShards(uuid: UUID, type: ShardType): Result { + @Suppress("unused") suspend fun getBankShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.BANK) + + @Suppress("unused") suspend fun getInventoryShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.INVENTORY) + + @Suppress("unused") suspend fun getEnderChestShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + + private suspend fun getShardTypeShards(uuid: UUID, type: ShardType): Result { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val playerShards = postgreSQL.getPlayerShards(uuid, type) - if (playerShards.isNeededShardTypeNull(type)) { - return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.ALL -> postgreSQL.getTotalShards(uuid) } - Result.success(playerShards) } ) { is LockResult.Acquired -> { @@ -230,9 +235,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return@withLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { + DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) } @@ -266,11 +269,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes) - if (transactionLogError) { - handleError(uuid, shards, null, null, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(uuid, shards, null, transactionReason, notes) + .getOrElse { handleError(uuid, shards, null, null, true) } Result.success(Unit) } @@ -319,17 +320,14 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return@withLockSuspend Result.failure(DiamondBankException.OtherException) } - val error = postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) return@withLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog(payerUuid, shards, receiverUuid, transactionReason, notes) - if (transactionLogError) { - handleError(payerUuid, shards, null, receiverUuid, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(payerUuid, shards, receiverUuid, transactionReason, notes) + .getOrElse { handleError(payerUuid, shards, null, receiverUuid, true) } Result.success(Unit) } @@ -371,23 +369,14 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) } - val error = postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) - if (error) { + postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) } - val transactionLogError = - DiamondBankOG.postgreSQL.insertTransactionLog( - payerUuid, - shards, - receiverUuid, - transactionReason, - notes, - ) - if (transactionLogError) { - handleError(payerUuid, shards, null, receiverUuid, true) - } + DiamondBankOG.postgreSQL + .insertTransactionLog(payerUuid, shards, receiverUuid, transactionReason, notes) + .getOrElse { handleError(payerUuid, shards, null, receiverUuid, true) } Result.success(Unit) } diff --git a/src/main/kotlin/net/trueog/diamondbankog/ErrorHandler.kt b/src/main/kotlin/net/trueog/diamondbankog/ErrorHandler.kt index e70fb89..aa6a1c8 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/ErrorHandler.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/ErrorHandler.kt @@ -24,15 +24,15 @@ internal object ErrorHandler { if (otherUuid != null) "Other Player UUID: $otherUuid" else "" }Expected Mutated Shards = $expectedMutatedShards${ if (playerShards != null) { - if (playerShards.shardsInBank != -1) "Player Bank Balance: ${playerShards.shardsInBank}" else "" + if (playerShards.bank != -1) "Player Bank Balance: ${playerShards.bank}" else "" } else "" }${ if (playerShards != null) { - if (playerShards.shardsInInventory != -1) "Player Inventory Balance: ${playerShards.shardsInInventory}" else "" + if (playerShards.inventory != -1) "Player Inventory Balance: ${playerShards.inventory}" else "" } else "" }${ if (playerShards != null) { - if (playerShards.shardsInEnderChest != -1) "Player Ender Chest Balance: ${playerShards.shardsInEnderChest}" else "" + if (playerShards.enderChest != -1) "Player Ender Chest Balance: ${playerShards.enderChest}" else "" } else "" } """ diff --git a/src/main/kotlin/net/trueog/diamondbankog/Events.kt b/src/main/kotlin/net/trueog/diamondbankog/Events.kt index 1e0d539..f0c7700 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/Events.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/Events.kt @@ -42,24 +42,20 @@ internal class Events : Listener { DiamondBankOG.scope.launch { val inventoryShards = event.player.inventory.countTotal() - var error = - DiamondBankOG.postgreSQL.setPlayerShards(event.player.uniqueId, inventoryShards, ShardType.INVENTORY) - if (error) { - handleError(event.player.uniqueId, inventoryShards, null) - return@launch - } + DiamondBankOG.postgreSQL + .setPlayerShards(event.player.uniqueId, inventoryShards, ShardType.INVENTORY) + .getOrElse { + handleError(event.player.uniqueId, inventoryShards, null) + return@launch + } val enderChestDiamonds = event.player.enderChest.countTotal() - error = - DiamondBankOG.postgreSQL.setPlayerShards( - event.player.uniqueId, - enderChestDiamonds, - ShardType.ENDER_CHEST, - ) - if (error) { - handleError(event.player.uniqueId, enderChestDiamonds, null) - return@launch - } + DiamondBankOG.postgreSQL + .setPlayerShards(event.player.uniqueId, enderChestDiamonds, ShardType.ENDER_CHEST) + .getOrElse { + handleError(event.player.uniqueId, enderChestDiamonds, null) + return@launch + } } } @@ -108,12 +104,12 @@ internal class Events : Listener { DiamondBankOG.transactionLock.withLockSuspend(player.uniqueId) { val inventoryShards = runOnMainThread { player.inventory.countTotal() } - val error = - DiamondBankOG.postgreSQL.setPlayerShards(player.uniqueId, inventoryShards, ShardType.INVENTORY) - if (error) { - handleError(player.uniqueId, inventoryShards, null) - return@withLockSuspend - } + DiamondBankOG.postgreSQL + .setPlayerShards(player.uniqueId, inventoryShards, ShardType.INVENTORY) + .getOrElse { + handleError(player.uniqueId, inventoryShards, null) + return@withLockSuspend + } } } } @@ -152,16 +148,12 @@ internal class Events : Listener { DiamondBankOG.scope.launch { DiamondBankOG.transactionLock.withLockSuspend(event.player.uniqueId) { val inventoryShards = runOnMainThread { event.player.inventory.countTotal() } - val error = - DiamondBankOG.postgreSQL.setPlayerShards( - event.player.uniqueId, - inventoryShards, - ShardType.INVENTORY, - ) - if (error) { - handleError(event.player.uniqueId, inventoryShards, null) - return@withLockSuspend - } + DiamondBankOG.postgreSQL + .setPlayerShards(event.player.uniqueId, inventoryShards, ShardType.INVENTORY) + .getOrElse { + handleError(event.player.uniqueId, inventoryShards, null) + return@withLockSuspend + } } } } @@ -324,24 +316,20 @@ internal class Events : Listener { else null, ) } - var error = - DiamondBankOG.postgreSQL.setPlayerShards(player.uniqueId, inventoryShards, ShardType.INVENTORY) - if (error) { - handleError(player.uniqueId, inventoryShards, null) - return@withLockSuspend - } + DiamondBankOG.postgreSQL + .setPlayerShards(player.uniqueId, inventoryShards, ShardType.INVENTORY) + .getOrElse { + handleError(player.uniqueId, inventoryShards, null) + return@withLockSuspend + } if (enderChestShards == null) return@withLockSuspend - error = - DiamondBankOG.postgreSQL.setPlayerShards( - player.uniqueId, - enderChestShards, - ShardType.ENDER_CHEST, - ) - if (error) { - handleError(player.uniqueId, enderChestShards, null) - return@withLockSuspend - } + DiamondBankOG.postgreSQL + .setPlayerShards(player.uniqueId, enderChestShards, ShardType.ENDER_CHEST) + .getOrElse { + handleError(player.uniqueId, enderChestShards, null) + return@withLockSuspend + } } } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/InventoryExtensions.kt b/src/main/kotlin/net/trueog/diamondbankog/InventoryExtensions.kt index dcdfe97..fd722e4 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/InventoryExtensions.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/InventoryExtensions.kt @@ -82,13 +82,13 @@ internal object InventoryExtensions { val leftOver = addMap[0]!!.amount - val error = DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, leftOver, ShardType.BANK) + val result = DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, leftOver, ShardType.BANK) player.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: The change of $leftOver Diamond ${if (leftOver == 1) "Shard" else "Shards"} has been deposited into your bank." ) ) - return error + return result.isFailure } /** ONLY USE FOR INVENTORIES THAT DO NOT HAVE A HOLDER (for example shulker boxes) */ @@ -106,8 +106,9 @@ internal object InventoryExtensions { if (inventoryAddMap.isNotEmpty()) { val inventoryLeftOver = inventoryAddMap[0]!!.amount - val error = DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, inventoryLeftOver, ShardType.BANK) - if (error) return true + DiamondBankOG.postgreSQL.addToPlayerShards(player.uniqueId, inventoryLeftOver, ShardType.BANK).getOrElse { + return true + } player.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: The change of ${leftOver - inventoryLeftOver} Diamond ${if (leftOver == 1) "Shard" else "Shards"} has been added to your inventory, and the remaining $inventoryLeftOver Diamond ${if (leftOver == 1) "Shard" else "Shards"} has been deposited into your bank." @@ -195,20 +196,16 @@ internal object InventoryExtensions { DiamondBankOG.scope.launch { DiamondBankOG.transactionLock.withLockSuspend(player.uniqueId) { val inventoryShards = player.inventory.countTotal() - val error = - DiamondBankOG.postgreSQL.setPlayerShards( - player.uniqueId, - inventoryShards, - ShardType.INVENTORY, - ) - if (error) { - handleError(player.uniqueId, inventoryShards, null) - player.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to recount the Diamonds amount in your inventory, try opening and closing your inventory to force a recount." + DiamondBankOG.postgreSQL + .setPlayerShards(player.uniqueId, inventoryShards, ShardType.INVENTORY) + .getOrElse { + handleError(player.uniqueId, inventoryShards, null) + player.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to recount the Diamonds amount in your inventory, try opening and closing your inventory to force a recount." + ) ) - ) - } + } } } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt index ee47cbc..a2d251d 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt @@ -12,6 +12,8 @@ import kotlinx.coroutines.future.await class PostgreSQL { lateinit var pool: ConnectionPool + class InvalidArgumentException : Exception() + enum class ShardType(val string: String) { BANK("bank_shards"), INVENTORY("inventory_shards"), @@ -78,42 +80,10 @@ class PostgreSQL { } } - data class PlayerShards(val shardsInBank: Int?, val shardsInInventory: Int?, val shardsInEnderChest: Int?) { - fun isNeededShardTypeNull(type: ShardType): Boolean { - when (type) { - ShardType.BANK -> { - if (this.shardsInBank == null) { - return true - } - } + data class PlayerShards(val bank: Int, val inventory: Int, val enderChest: Int) - ShardType.INVENTORY -> { - if (this.shardsInInventory == null) { - return true - } - } - - ShardType.ENDER_CHEST -> { - if (this.shardsInEnderChest == null) { - return true - } - } - - ShardType.ALL -> { - if ( - this.shardsInBank == null || this.shardsInInventory == null || this.shardsInEnderChest == null - ) { - return true - } - } - } - return false - } - } - - /** @return True if failed */ - suspend fun setPlayerShards(uuid: UUID, shards: Int, type: ShardType): Boolean { - if (type == ShardType.ALL) return true + suspend fun setPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { + if (type == ShardType.ALL) return Result.failure(InvalidArgumentException()) try { val connection = pool.asSuspending.connect() @@ -123,54 +93,130 @@ class PostgreSQL { listOf(uuid, shards), ) preparedStatement.await() - } catch (_: Exception) { - return true + } catch (e: Exception) { + return Result.failure(e) } - return false + return Result.success(Unit) } - /** @return True if failed */ - suspend fun addToPlayerShards(uuid: UUID, shards: Int, type: ShardType): Boolean { - if (type == ShardType.ALL) return true + suspend fun addToPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { + if (type == ShardType.ALL) return Result.failure(InvalidArgumentException()) - val playerDiamonds = getPlayerShardsWrapper(uuid, type) ?: return true + val playerShards = + when (type) { + ShardType.BANK -> getBankShards(uuid) + ShardType.INVENTORY -> getInventoryShards(uuid) + ShardType.ENDER_CHEST -> getEnderChestShards(uuid) + else -> { + return Result.failure(InvalidArgumentException()) + } + } - val error = setPlayerShards(uuid, playerDiamonds + shards, type) - return error + playerShards.exceptionOrNull()?.let { + return Result.failure(it) + } + + return setPlayerShards(uuid, playerShards.getOrThrow() + shards, type) } - /** @return True if failed */ - suspend fun subtractFromPlayerShards(uuid: UUID, shards: Int, type: ShardType): Boolean { - if (type == ShardType.ALL) return true + suspend fun subtractFromBankShards(uuid: UUID, shards: Int): Result { + val bankShards = getBankShards(uuid) + bankShards.exceptionOrNull()?.let { + return Result.failure(it) + } - val playerDiamonds = getPlayerShardsWrapper(uuid, type) ?: return true - - val error = setPlayerShards(uuid, playerDiamonds - shards, type) - return error + return setPlayerShards(uuid, bankShards.getOrThrow() - shards, ShardType.BANK) } - private suspend fun getPlayerShardsWrapper(uuid: UUID, type: ShardType): Int? { - val getResponse = getPlayerShards(uuid, type) + suspend fun getBankShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.BANK) - return when (type) { - ShardType.BANK -> getResponse.shardsInBank - ShardType.INVENTORY -> getResponse.shardsInInventory - ShardType.ENDER_CHEST -> getResponse.shardsInEnderChest - ShardType.ALL -> - if ( - getResponse.shardsInBank != null && - getResponse.shardsInInventory != null && - getResponse.shardsInEnderChest != null + suspend fun getInventoryShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.INVENTORY) + + suspend fun getEnderChestShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + + suspend fun getTotalShards(uuid: UUID): Result { + var totalShards: Int? + try { + val connection = pool.asSuspending.connect() + + val preparedStatement = + connection.sendPreparedStatement( + "SELECT bank_shards, inventory_shards, ender_chest_shards FROM ${Config.postgresTable} WHERE uuid = ? LIMIT 1", + listOf(uuid), ) - getResponse.shardsInBank + getResponse.shardsInInventory + getResponse.shardsInEnderChest - else null + val result = preparedStatement.await() + + totalShards = + if (result.rows.isNotEmpty()) { + val rowData = result.rows[0] as ArrayRowData + val bankShards = + if (rowData.columns[0] != null) { + rowData.columns[0] as Int + } else 0 + val inventoryShards = + if (rowData.columns[1] != null) { + rowData.columns[1] as Int + } else 0 + val enderChestShards = + if (rowData.columns[2] != null) { + rowData.columns[2] as Int + } else 0 + + bankShards + inventoryShards + enderChestShards + } else { + 0 + } + } catch (e: Exception) { + DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) } + + return Result.success(totalShards) } - suspend fun getPlayerShards(uuid: UUID, type: ShardType): PlayerShards { - var bankShards: Int? = null - var inventoryShards: Int? = null - var enderChestShards: Int? = null + suspend fun getAllShards(uuid: UUID): Result { + var bankShards: Int? + var inventoryShards: Int? + var enderChestShards: Int? + try { + val connection = pool.asSuspending.connect() + + val preparedStatement = + connection.sendPreparedStatement( + "SELECT bank_shards, inventory_shards, ender_chest_shards FROM ${Config.postgresTable} WHERE uuid = ? LIMIT 1", + listOf(uuid), + ) + val result = preparedStatement.await() + + if (result.rows.isNotEmpty()) { + val rowData = result.rows[0] as ArrayRowData + bankShards = + if (rowData.columns[0] != null) { + rowData.columns[0] as Int + } else 0 + inventoryShards = + if (rowData.columns[1] != null) { + rowData.columns[1] as Int + } else 0 + enderChestShards = + if (rowData.columns[2] != null) { + rowData.columns[2] as Int + } else 0 + } else { + bankShards = 0 + inventoryShards = 0 + enderChestShards = 0 + } + } catch (e: Exception) { + DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) + } + + return Result.success(PlayerShards(bankShards, inventoryShards, enderChestShards)) + } + + private suspend fun getShardTypeShards(uuid: UUID, type: ShardType): Result { + var shards: Int? try { val connection = pool.asSuspending.connect() @@ -181,56 +227,21 @@ class PostgreSQL { ) val result = preparedStatement.await() - if (result.rows.isNotEmpty()) { - val rowData = result.rows[0] as ArrayRowData - - when (type) { - ShardType.BANK -> { - bankShards = - if (rowData.columns[0] != null) { - rowData.columns[0] as Int - } else 0 - } - - ShardType.INVENTORY -> { - inventoryShards = - if (rowData.columns[0] != null) { - rowData.columns[0] as Int - } else 0 - } - - ShardType.ENDER_CHEST -> { - enderChestShards = - if (rowData.columns[0] != null) { - rowData.columns[0] as Int - } else 0 - } - - ShardType.ALL -> { - bankShards = - if (rowData.columns[0] != null) { - rowData.columns[0] as Int - } else 0 - inventoryShards = - if (rowData.columns[1] != null) { - rowData.columns[1] as Int - } else 0 - enderChestShards = - if (rowData.columns[2] != null) { - rowData.columns[2] as Int - } else 0 - } + shards = + if (result.rows.isNotEmpty()) { + val rowData = result.rows[0] as ArrayRowData + if (rowData.columns[0] != null) { + rowData.columns[0] as Int + } else 0 + } else { + 0 } - } else { - bankShards = 0 - inventoryShards = 0 - enderChestShards = 0 - } } catch (e: Exception) { DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) } - return PlayerShards(bankShards, inventoryShards, enderChestShards) + return Result.success(shards) } suspend fun getBaltop(offset: Int): Map? { @@ -339,14 +350,13 @@ class PostgreSQL { return number } - /** @return True if failed */ suspend fun insertTransactionLog( playerUuid: UUID, transferredShards: Int, playerToUuid: UUID?, transactionReason: String, notes: String?, - ): Boolean { + ): Result { try { val connection = pool.asSuspending.connect() @@ -358,8 +368,8 @@ class PostgreSQL { ) preparedStatement.await() } catch (_: Exception) { - return true + return Result.failure(Exception()) } - return false + return Result.success(Unit) } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/WithdrawHelper.kt b/src/main/kotlin/net/trueog/diamondbankog/WithdrawHelper.kt index 9c2e2e8..bdfd53c 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/WithdrawHelper.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/WithdrawHelper.kt @@ -3,30 +3,19 @@ package net.trueog.diamondbankog import kotlin.math.floor import net.trueog.diamondbankog.ErrorHandler.handleError import net.trueog.diamondbankog.InventoryExtensions.withdraw -import net.trueog.diamondbankog.PostgreSQL.ShardType import org.bukkit.entity.Player internal object WithdrawHelper { /** @return The amount of not removed shards, -1 if error */ suspend fun withdrawFromPlayer(player: Player, shards: Int): Int { - val playerShards = DiamondBankOG.postgreSQL.getPlayerShards(player.uniqueId, ShardType.ALL) - if ( - playerShards.shardsInBank == null || - playerShards.shardsInInventory == null || - playerShards.shardsInEnderChest == null - ) { - return -1 - } + val playerShards = + DiamondBankOG.postgreSQL.getAllShards(player.uniqueId).getOrElse { + return -1 + } // Withdraw everything if (shards == -1) { - val error = - DiamondBankOG.postgreSQL.subtractFromPlayerShards( - player.uniqueId, - playerShards.shardsInBank, - ShardType.BANK, - ) - if (error) { + DiamondBankOG.postgreSQL.subtractFromBankShards(player.uniqueId, playerShards.bank).getOrElse { handleError(player.uniqueId, shards, playerShards) player.sendMessage( DiamondBankOG.mm.deserialize( @@ -36,22 +25,18 @@ internal object WithdrawHelper { return -1 } - val notRemovedInventory = player.inventory.withdraw(playerShards.shardsInInventory) + val notRemovedInventory = player.inventory.withdraw(playerShards.inventory) - val notRemovedEnderChest = player.enderChest.withdraw(playerShards.shardsInEnderChest) + val notRemovedEnderChest = player.enderChest.withdraw(playerShards.enderChest) return notRemovedInventory + notRemovedEnderChest } - if (shards > playerShards.shardsInBank + playerShards.shardsInInventory + playerShards.shardsInEnderChest) { + if (shards > playerShards.bank + playerShards.inventory + playerShards.enderChest) { val diamonds = String.format("%.1f", floor((shards / 9.0) * 10) / 10.0) val totalDiamonds = String.format( "%.1f", - floor( - ((playerShards.shardsInBank + - playerShards.shardsInInventory + - playerShards.shardsInEnderChest) / 9.0) * 10 - ) / 10.0, + floor(((playerShards.bank + playerShards.inventory + playerShards.enderChest) / 9.0) * 10) / 10.0, ) player.sendMessage( DiamondBankOG.mm.deserialize( @@ -61,9 +46,8 @@ internal object WithdrawHelper { return -1 } - if (shards <= playerShards.shardsInBank) { - val error = DiamondBankOG.postgreSQL.subtractFromPlayerShards(player.uniqueId, shards, ShardType.BANK) - if (error) { + if (shards <= playerShards.bank) { + DiamondBankOG.postgreSQL.subtractFromBankShards(player.uniqueId, shards).getOrElse { handleError(player.uniqueId, shards, playerShards) player.sendMessage( DiamondBankOG.mm.deserialize( @@ -75,14 +59,8 @@ internal object WithdrawHelper { return 0 } - if (shards <= playerShards.shardsInBank + playerShards.shardsInInventory) { - val error = - DiamondBankOG.postgreSQL.subtractFromPlayerShards( - player.uniqueId, - playerShards.shardsInBank, - ShardType.BANK, - ) - if (error) { + if (shards <= playerShards.bank + playerShards.inventory) { + DiamondBankOG.postgreSQL.subtractFromBankShards(player.uniqueId, playerShards.bank).getOrElse { handleError(player.uniqueId, shards, playerShards) player.sendMessage( DiamondBankOG.mm.deserialize( @@ -92,17 +70,11 @@ internal object WithdrawHelper { return -1 } - val notRemoved = player.inventory.withdraw(shards - playerShards.shardsInBank) + val notRemoved = player.inventory.withdraw(shards - playerShards.bank) return notRemoved } - val error = - DiamondBankOG.postgreSQL.subtractFromPlayerShards( - player.uniqueId, - playerShards.shardsInBank, - ShardType.BANK, - ) - if (error) { + DiamondBankOG.postgreSQL.subtractFromBankShards(player.uniqueId, playerShards.bank).getOrElse { handleError(player.uniqueId, shards, playerShards) player.sendMessage( DiamondBankOG.mm.deserialize( @@ -112,10 +84,9 @@ internal object WithdrawHelper { return -1 } - val notRemovedInventory = player.inventory.withdraw(playerShards.shardsInInventory) + val notRemovedInventory = player.inventory.withdraw(playerShards.inventory) - val notRemovedEnderChest = - player.enderChest.withdraw(shards - (playerShards.shardsInBank + playerShards.shardsInInventory)) + val notRemovedEnderChest = player.enderChest.withdraw(shards - (playerShards.bank + playerShards.inventory)) return notRemovedInventory + notRemovedEnderChest } diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Balance.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Balance.kt index 95b0736..88b0c3b 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Balance.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Balance.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.launch import net.trueog.diamondbankog.Config import net.trueog.diamondbankog.DiamondBankOG import net.trueog.diamondbankog.PlayerPrefix.getPrefix -import net.trueog.diamondbankog.PostgreSQL.ShardType import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor @@ -61,24 +60,21 @@ internal class Balance : CommandExecutor { return@launch } - val balance = DiamondBankOG.postgreSQL.getPlayerShards(otherPlayer.uniqueId, ShardType.ALL) - if ( - balance.shardsInBank == null || - balance.shardsInInventory == null || - balance.shardsInEnderChest == null - ) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get their balance." + val balance = + DiamondBankOG.postgreSQL.getAllShards(otherPlayer.uniqueId).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get their balance." + ) ) - ) - return@launch - } - val totalBalance = balance.shardsInBank + balance.shardsInInventory + balance.shardsInEnderChest + return@launch + } + + val totalBalance = balance.bank + balance.inventory + balance.enderChest val totalDiamonds = String.format("%.1f", floor((totalBalance / 9.0) * 10) / 10.0) - val bankDiamonds = String.format("%.1f", floor((balance.shardsInBank / 9.0) * 10) / 10.0) - val inventoryDiamonds = String.format("%.1f", floor((balance.shardsInInventory / 9.0) * 10) / 10.0) - val enderChestDiamonds = String.format("%.1f", floor((balance.shardsInEnderChest / 9.0) * 10) / 10.0) + val bankDiamonds = String.format("%.1f", floor((balance.bank / 9.0) * 10) / 10.0) + val inventoryDiamonds = String.format("%.1f", floor((balance.inventory / 9.0) * 10) / 10.0) + val enderChestDiamonds = String.format("%.1f", floor((balance.enderChest / 9.0) * 10) / 10.0) sender.sendMessage( DiamondBankOG.mm.deserialize( "Balance of ${getPrefix(otherPlayer.uniqueId)}${otherPlayer.name}:\n" + @@ -119,22 +115,23 @@ internal class Balance : CommandExecutor { } otherPlayer } - val balance = DiamondBankOG.postgreSQL.getPlayerShards(balancePlayer.uniqueId, ShardType.ALL) - if (balance.isNeededShardTypeNull(ShardType.ALL)) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get ${ + val balance = + DiamondBankOG.postgreSQL.getAllShards(balancePlayer.uniqueId).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get ${ if (balancePlayer.uniqueId != sender.uniqueId) "their" else "your" } balance." + ) ) - ) - return@launch - } - val totalBalance = balance.shardsInBank!! + balance.shardsInInventory!! + balance.shardsInEnderChest!! + return@launch + } + + val totalBalance = balance.bank + balance.inventory + balance.enderChest val totalDiamonds = String.format("%.1f", floor((totalBalance / 9.0) * 10) / 10.0) - val bankDiamonds = String.format("%.1f", floor((balance.shardsInBank / 9.0) * 10) / 10.0) - val inventoryDiamonds = String.format("%.1f", floor((balance.shardsInInventory / 9.0) * 10) / 10.0) - val enderChestDiamonds = String.format("%.1f", floor((balance.shardsInEnderChest / 9.0) * 10) / 10.0) + val bankDiamonds = String.format("%.1f", floor((balance.bank / 9.0) * 10) / 10.0) + val inventoryDiamonds = String.format("%.1f", floor((balance.inventory / 9.0) * 10) / 10.0) + val enderChestDiamonds = String.format("%.1f", floor((balance.enderChest / 9.0) * 10) / 10.0) sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: ${ diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt index 54c460f..cf7797b 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt @@ -70,15 +70,14 @@ internal class Deposit : CommandExecutor { } val playerInventoryShards = - DiamondBankOG.postgreSQL.getPlayerShards(sender.uniqueId, ShardType.INVENTORY).shardsInInventory - if (playerInventoryShards == null) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get your balance." + DiamondBankOG.postgreSQL.getInventoryShards(sender.uniqueId).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get your balance." + ) ) - ) - return@launch - } + return@launch + } if (playerInventoryShards == 0) { sender.sendMessage( DiamondBankOG.mm.deserialize( @@ -152,8 +151,7 @@ internal class Deposit : CommandExecutor { ) } - val error = DiamondBankOG.postgreSQL.addToPlayerShards(sender.uniqueId, shards, ShardType.BANK) - if (error) { + DiamondBankOG.postgreSQL.addToPlayerShards(sender.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, PlayerShards(-1, playerInventoryShards, -1)) sender.sendMessage( DiamondBankOG.mm.deserialize( @@ -188,8 +186,8 @@ internal class Deposit : CommandExecutor { ) ) - val error = - DiamondBankOG.postgreSQL.insertTransactionLog( + DiamondBankOG.postgreSQL + .insertTransactionLog( sender.uniqueId, shards, null, @@ -197,9 +195,7 @@ internal class Deposit : CommandExecutor { if (shards != originalShards) "Could not withdraw $originalShards shards, continued with $shards" else null, ) - if (error) { - handleError(sender.uniqueId, shards, null, null, true) - } + .getOrElse { handleError(sender.uniqueId, shards, null, null, true) } } return true } diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt index 64808d1..2ad1dfc 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt @@ -149,17 +149,17 @@ internal class Pay : CommandExecutor { ) } - val error = - DiamondBankOG.postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) - if (error) { - handleError(sender.uniqueId, shards, null, receiver.uniqueId) - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: A severe error has occurred. Please notify a staff member." + DiamondBankOG.postgreSQL + .addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK) + .getOrElse { + handleError(sender.uniqueId, shards, null, receiver.uniqueId) + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: A severe error has occurred. Please notify a staff member." + ) ) - ) - return@tryWithLockSuspend true - } + return@tryWithLockSuspend true + } false } ) { @@ -204,8 +204,8 @@ internal class Pay : CommandExecutor { ) } - val error = - DiamondBankOG.postgreSQL.insertTransactionLog( + DiamondBankOG.postgreSQL + .insertTransactionLog( sender.uniqueId, shards, receiver.uniqueId, @@ -213,9 +213,7 @@ internal class Pay : CommandExecutor { if (shards != originalShards) "Could not withdraw $originalShards shards, continued with $shards" else null, ) - if (error) { - handleError(sender.uniqueId, shards, null, receiver.uniqueId, true) - } + .getOrElse { handleError(sender.uniqueId, shards, null, receiver.uniqueId, true) } } return true } diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/SetBankBalance.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/SetBankBalance.kt index 7cab567..92dd05e 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/SetBankBalance.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/SetBankBalance.kt @@ -74,8 +74,7 @@ internal class SetBankBalance : CommandExecutor { return@launch } - var error = DiamondBankOG.postgreSQL.setPlayerShards(player.uniqueId, balance, ShardType.BANK) - if (error) { + DiamondBankOG.postgreSQL.setPlayerShards(player.uniqueId, balance, ShardType.BANK).getOrElse { sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: Something went wrong while trying to set that player's balance." @@ -83,6 +82,7 @@ internal class SetBankBalance : CommandExecutor { ) return@launch } + sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: Successfully set the balance of ${ @@ -93,17 +93,15 @@ internal class SetBankBalance : CommandExecutor { ) ) - error = - DiamondBankOG.postgreSQL.insertTransactionLog( + DiamondBankOG.postgreSQL + .insertTransactionLog( player.uniqueId, balance, null, "Set Bank Balance", "Bank Balance set by ${if (sender is Player) "${sender.uniqueId}" else "console"}", ) - if (error) { - handleError(player.uniqueId, balance, null, null, true) - } + .getOrElse { handleError(player.uniqueId, balance, null, null, true) } } return true } diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt index 7dc3777..b2451da 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt @@ -99,24 +99,20 @@ internal class Withdraw : CommandExecutor { shards = (split[0].toInt() * 9) + split[1].toInt() } - val result = + val lockResult = DiamondBankOG.transactionLock.tryWithLockSuspend(sender.uniqueId) { - val playerShards = DiamondBankOG.postgreSQL.getPlayerShards(sender.uniqueId, ShardType.ALL) - if ( - playerShards.shardsInBank == null || - playerShards.shardsInInventory == null || - playerShards.shardsInEnderChest == null - ) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get your balance." + val playerShards = + DiamondBankOG.postgreSQL.getAllShards(sender.uniqueId).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get your balance." + ) ) - ) - return@tryWithLockSuspend true - } + return@tryWithLockSuspend true + } - val playerBankShards = playerShards.shardsInBank - val playerInventoryShards = playerShards.shardsInInventory + val playerBankShards = playerShards.bank + val playerInventoryShards = playerShards.inventory if (shards == -1) shards = playerBankShards @@ -164,9 +160,7 @@ internal class Withdraw : CommandExecutor { return@tryWithLockSuspend true } - var error = - DiamondBankOG.postgreSQL.subtractFromPlayerShards(sender.uniqueId, shards, ShardType.BANK) - if (error) { + DiamondBankOG.postgreSQL.subtractFromBankShards(sender.uniqueId, shards).getOrElse { handleError(sender.uniqueId, shards, PostgreSQL.PlayerShards(playerBankShards, -1, -1)) sender.sendMessage( DiamondBankOG.mm.deserialize( @@ -196,8 +190,7 @@ internal class Withdraw : CommandExecutor { return@tryWithLockSuspend true } - error = DiamondBankOG.postgreSQL.addToPlayerShards(sender.uniqueId, shards, ShardType.INVENTORY) - if (error) { + DiamondBankOG.postgreSQL.addToPlayerShards(sender.uniqueId, shards, ShardType.INVENTORY).getOrElse { handleError(sender.uniqueId, shards, playerShards) sender.sendMessage( DiamondBankOG.mm.deserialize( @@ -208,9 +201,9 @@ internal class Withdraw : CommandExecutor { } false } - when (result) { + when (lockResult) { is TransactionLock.LockResult.Acquired -> { - if (result.result) { + if (lockResult.result) { return@launch } } @@ -232,8 +225,7 @@ internal class Withdraw : CommandExecutor { ) ) - val error = DiamondBankOG.postgreSQL.insertTransactionLog(sender.uniqueId, shards, null, "Withdraw", null) - if (error) { + DiamondBankOG.postgreSQL.insertTransactionLog(sender.uniqueId, shards, null, "Withdraw", null).getOrElse { handleError(sender.uniqueId, shards, null, null, true) } } -- 2.47.3 From d5aef45fdc52c55c02931830635f2af363bd9296 Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 00:04:45 +0200 Subject: [PATCH 3/8] Add getTotal and getAll APIs --- .../diamondbankog/DiamondBankAPIJava.kt | 71 ++++++++++++++++++- .../diamondbankog/DiamondBankAPIKotlin.kt | 35 ++++++++- .../net/trueog/diamondbankog/PostgreSQL.kt | 6 +- 3 files changed, 105 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index c127971..e5dea65 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -2,10 +2,12 @@ package net.trueog.diamondbankog import java.util.* import java.util.concurrent.CompletableFuture +import kotlin.getOrThrow import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.future.future import kotlinx.coroutines.runBlocking import net.trueog.diamondbankog.ErrorHandler.handleError +import net.trueog.diamondbankog.PostgreSQL.PlayerShards import net.trueog.diamondbankog.PostgreSQL.ShardType import net.trueog.diamondbankog.TransactionLock.LockResult import org.bukkit.Bukkit @@ -176,6 +178,35 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { @Suppress("unused") fun blockingGetEnderChestShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) + /** + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released + * + * @throws DiamondBankException.EconomyDisabledException + * @throws java.lang.Exception + */ + @Suppress("unused") fun blockingGetTotalShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.TOTAL) + + /** + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released + * + * @throws DiamondBankException.EconomyDisabledException + * @throws java.lang.Exception + */ + @Suppress("unused") + fun blockingGetAllShards(uuid: UUID): PlayerShards { + if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException + + return runBlocking { + DiamondBankOG.transactionLock.withLockSuspend(uuid) { + val result = postgreSQL.getAllShards(uuid) + result.exceptionOrNull()?.let { throw it } + result.getOrThrow() + } + } + } + private fun blockingGetShardTypeShards(uuid: UUID, type: ShardType): Int { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -186,7 +217,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.ALL -> postgreSQL.getTotalShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } result.exceptionOrNull()?.let { throw it } @@ -221,6 +252,42 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { */ @Suppress("unused") fun getEnderChestShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + /** + * WARNING: do not run on a thread where blocking is unacceptable + * + * @throws DiamondBankException.EconomyDisabledException + * @throws DiamondBankException.TransactionsLockedException + * @throws java.lang.Exception + */ + @Suppress("unused") fun getTotalShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.TOTAL) + + /** + * WARNING: do not run on a thread where blocking is unacceptable + * + * @throws DiamondBankException.EconomyDisabledException + * @throws DiamondBankException.TransactionsLockedException + * @throws java.lang.Exception + */ + @Suppress("unused") + fun getAllShards(uuid: UUID): PlayerShards { + if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException + + return runBlocking { + when ( + val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } + ) { + is LockResult.Acquired -> { + result.result.exceptionOrNull()?.let { throw it } + result.result.getOrThrow() + } + + LockResult.Failed -> { + throw DiamondBankException.TransactionsLockedException + } + } + } + } + private fun getShardTypeShards(uuid: UUID, type: ShardType): Int { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -232,7 +299,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.ALL -> postgreSQL.getTotalShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } ) { diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt index 6f737d4..716104b 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt @@ -3,6 +3,7 @@ package net.trueog.diamondbankog import java.util.* import kotlinx.coroutines.DelicateCoroutinesApi import net.trueog.diamondbankog.ErrorHandler.handleError +import net.trueog.diamondbankog.PostgreSQL.PlayerShards import net.trueog.diamondbankog.PostgreSQL.ShardType import net.trueog.diamondbankog.TransactionLock.LockResult import org.bukkit.Bukkit @@ -152,6 +153,17 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { suspend fun blockingGetEnderChestShards(uuid: UUID): Result = blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) + /** WARNING: blocking, if the player has a transaction lock applied this function will wait until its released */ + @Suppress("unused") + suspend fun blockingGetTotalShards(uuid: UUID): Result = blockingGetShardTypeShards(uuid, ShardType.TOTAL) + + /** WARNING: blocking, if the player has a transaction lock applied this function will wait until its released */ + @Suppress("unused") + suspend fun blockingGetAllShards(uuid: UUID): Result { + if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) + return postgreSQL.getAllShards(uuid) + } + private suspend fun blockingGetShardTypeShards(uuid: UUID, type: ShardType): Result { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) @@ -160,7 +172,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.ALL -> postgreSQL.getTotalShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } } @@ -171,6 +183,25 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { @Suppress("unused") suspend fun getEnderChestShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + @Suppress("unused") suspend fun getTotalShards(uuid: UUID) = getShardTypeShards(uuid, ShardType.TOTAL) + + @Suppress("unused") + suspend fun getAllShards(uuid: UUID): Result { + if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) + + return when ( + val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } + ) { + is LockResult.Acquired -> { + result.result + } + + LockResult.Failed -> { + return Result.failure(DiamondBankException.TransactionsLockedException) + } + } + } + private suspend fun getShardTypeShards(uuid: UUID, type: ShardType): Result { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) @@ -181,7 +212,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.ALL -> postgreSQL.getTotalShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } ) { diff --git a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt index a2d251d..f89c53b 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt @@ -18,7 +18,7 @@ class PostgreSQL { BANK("bank_shards"), INVENTORY("inventory_shards"), ENDER_CHEST("ender_chest_shards"), - ALL("bank_shards, inventory_shards, ender_chest_shards"), + TOTAL("bank_shards, inventory_shards, ender_chest_shards"), } @Throws(SQLException::class, ClassNotFoundException::class) @@ -83,7 +83,7 @@ class PostgreSQL { data class PlayerShards(val bank: Int, val inventory: Int, val enderChest: Int) suspend fun setPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { - if (type == ShardType.ALL) return Result.failure(InvalidArgumentException()) + if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException()) try { val connection = pool.asSuspending.connect() @@ -100,7 +100,7 @@ class PostgreSQL { } suspend fun addToPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { - if (type == ShardType.ALL) return Result.failure(InvalidArgumentException()) + if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException()) val playerShards = when (type) { -- 2.47.3 From 68d2b7b30bf86c29544b3565a455f8996c30e35c Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 00:10:05 +0200 Subject: [PATCH 4/8] Cleanup --- .../diamondbankog/DiamondBankAPIJava.kt | 40 ++++------------ .../diamondbankog/DiamondBankAPIKotlin.kt | 48 +++++-------------- .../trueog/diamondbankog/commands/Compress.kt | 2 +- .../trueog/diamondbankog/commands/Deposit.kt | 2 +- .../net/trueog/diamondbankog/commands/Pay.kt | 2 +- .../trueog/diamondbankog/commands/Withdraw.kt | 2 +- 6 files changed, 26 insertions(+), 70 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index e5dea65..bcbfeb7 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -71,13 +71,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { .getOrElse { handleError(uuid, shards, null, null, true) } } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } @@ -138,13 +134,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { .getOrElse { handleError(uuid, shards, null, null, true) } } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } @@ -281,9 +273,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { result.result.getOrThrow() } - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } @@ -308,9 +298,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { result.result.getOrThrow() } - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } @@ -428,13 +416,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { .getOrElse { handleError(uuid, shards, null, null, true) } } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } @@ -550,13 +534,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { .getOrElse { handleError(payerUuid, shards, null, receiverUuid, true) } } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - throw DiamondBankException.TransactionsLockedException - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt index 716104b..2b295ac 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt @@ -64,13 +64,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { Result.success(Unit) } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - return Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } @@ -129,13 +125,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { Result.success(Unit) } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } @@ -192,13 +184,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - return Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } @@ -216,13 +204,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { } } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - return Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } @@ -307,13 +291,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { Result.success(Unit) } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } @@ -412,13 +392,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { Result.success(Unit) } ) { - is LockResult.Acquired -> { - result.result - } + is LockResult.Acquired -> result.result - LockResult.Failed -> { - Result.failure(DiamondBankException.TransactionsLockedException) - } + is LockResult.Failed -> throw DiamondBankException.TransactionsLockedException } } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Compress.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Compress.kt index 01955d1..377e323 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Compress.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Compress.kt @@ -241,7 +241,7 @@ internal class Compress : CommandExecutor { result.result } - TransactionLock.LockResult.Failed -> { + is TransactionLock.LockResult.Failed -> { sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: You are currently blocked from using /deposit." diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt index cf7797b..14ad460 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Deposit.kt @@ -169,7 +169,7 @@ internal class Deposit : CommandExecutor { } } - TransactionLock.LockResult.Failed -> { + is TransactionLock.LockResult.Failed -> { sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: You are currently blocked from using /deposit." diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt index 2ad1dfc..dcf804d 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Pay.kt @@ -169,7 +169,7 @@ internal class Pay : CommandExecutor { } } - TransactionLock.LockResult.Failed -> { + is TransactionLock.LockResult.Failed -> { sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: You are currently blocked from using /pay." diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt index b2451da..a96ea2d 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Withdraw.kt @@ -208,7 +208,7 @@ internal class Withdraw : CommandExecutor { } } - TransactionLock.LockResult.Failed -> { + is TransactionLock.LockResult.Failed -> { sender.sendMessage( DiamondBankOG.mm.deserialize( "${Config.prefix}: You are currently blocked from using /withdraw." -- 2.47.3 From e2ef927e698fe9cd588860d29b0a91c60667ff91 Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 00:20:09 +0200 Subject: [PATCH 5/8] Add missing @Throws annotations --- .../diamondbankog/DiamondBankAPIJava.kt | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index bcbfeb7..7c762f4 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -148,7 +148,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws java.lang.Exception */ - @Suppress("unused") fun blockingGetBankShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.BANK) + @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Suppress("unused") + fun blockingGetBankShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.BANK) /** * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction @@ -157,6 +159,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws java.lang.Exception */ + @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) @Suppress("unused") fun blockingGetInventoryShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.INVENTORY) @@ -167,6 +170,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws java.lang.Exception */ + @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) @Suppress("unused") fun blockingGetEnderChestShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) @@ -177,7 +181,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws java.lang.Exception */ - @Suppress("unused") fun blockingGetTotalShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.TOTAL) + @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Suppress("unused") + fun blockingGetTotalShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.TOTAL) /** * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction @@ -186,6 +192,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws java.lang.Exception */ + @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) @Suppress("unused") fun blockingGetAllShards(uuid: UUID): PlayerShards { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -224,7 +231,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.TransactionsLockedException * @throws java.lang.Exception */ - @Suppress("unused") fun getBankShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.BANK) + @Throws( + DiamondBankException.EconomyDisabledException::class, + DiamondBankException.TransactionsLockedException::class, + Exception::class, + ) + @Suppress("unused") + fun getBankShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.BANK) /** * WARNING: do not run on a thread where blocking is unacceptable @@ -233,7 +246,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.TransactionsLockedException * @throws java.lang.Exception */ - @Suppress("unused") fun getInventoryShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.INVENTORY) + @Throws( + DiamondBankException.EconomyDisabledException::class, + DiamondBankException.TransactionsLockedException::class, + Exception::class, + ) + @Suppress("unused") + fun getInventoryShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.INVENTORY) /** * WARNING: do not run on a thread where blocking is unacceptable @@ -242,7 +261,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.TransactionsLockedException * @throws java.lang.Exception */ - @Suppress("unused") fun getEnderChestShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.ENDER_CHEST) + @Throws( + DiamondBankException.EconomyDisabledException::class, + DiamondBankException.TransactionsLockedException::class, + Exception::class, + ) + @Suppress("unused") + fun getEnderChestShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.ENDER_CHEST) /** * WARNING: do not run on a thread where blocking is unacceptable @@ -251,7 +276,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.TransactionsLockedException * @throws java.lang.Exception */ - @Suppress("unused") fun getTotalShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.TOTAL) + @Throws( + DiamondBankException.EconomyDisabledException::class, + DiamondBankException.TransactionsLockedException::class, + Exception::class, + ) + @Suppress("unused") + fun getTotalShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.TOTAL) /** * WARNING: do not run on a thread where blocking is unacceptable -- 2.47.3 From 1d28b7ac9f80d238575bd16647f30fe74f61c2e2 Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 00:25:31 +0200 Subject: [PATCH 6/8] Remove unneeded hack --- build.gradle.kts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1dec210..f2ce0f7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,6 @@ plugins { kotlin("jvm") version "2.1.21" // Import kotlin jvm plugin for kotlin/java integration. id("com.diffplug.spotless") version "7.0.4" id("com.gradleup.shadow") version "8.3.6" // Import shadow API. - id("maven-publish") eclipse // Import eclipse plugin for IDE integration. } @@ -42,7 +41,6 @@ configurations.all { exclude(group = "io.projectreactor") } tasks.build { dependsOn(tasks.spotlessApply) dependsOn(tasks.shadowJar) - dependsOn(tasks.publishToMavenLocal) } tasks.jar { archiveClassifier.set("part") } @@ -75,17 +73,6 @@ tasks.withType().configureEach { isReproducibleFileOrder = true } -publishing { - publications { - create("shadow") { - groupId = "net.trueog.diamondbank-og" - artifactId = "diamondbank-og" - version = project.version.toString() - artifact(tasks.shadowJar) - } - } -} - spotless { kotlin { ktfmt().kotlinlangStyle().configure { it.setMaxWidth(120) } } kotlinGradle { -- 2.47.3 From f8cbecd7bc51e56672da6f69dd8570c3161a6cf4 Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 15:08:51 +0200 Subject: [PATCH 7/8] More clear exceptions and fix up throws again --- .../diamondbankog/DiamondBankAPIJava.kt | 107 ++++++++++-------- .../diamondbankog/DiamondBankAPIKotlin.kt | 34 ++++-- .../diamondbankog/DiamondBankException.kt | 2 + 3 files changed, 88 insertions(+), 55 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index 7c762f4..cc78744 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -21,16 +21,16 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingAddToPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -47,7 +47,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, @@ -63,7 +63,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL @@ -85,16 +85,16 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @param transactionReason the reason for this transaction for in the transaction log * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingSubtractFromPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { - postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { throw DiamondBankException.OtherException } + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) @@ -110,12 +110,12 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @param notes any specifics for this transaction that may be nice to know for in the transaction log * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.TransactionsLockedException::class, - DiamondBankException.OtherException::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun subtractFromPlayerBankShards(uuid: UUID, shards: Int, transactionReason: String, notes: String?) { @@ -126,7 +126,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL @@ -146,9 +146,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingGetBankShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.BANK) @@ -157,9 +157,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingGetInventoryShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.INVENTORY) @@ -168,9 +168,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingGetEnderChestShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.ENDER_CHEST) @@ -179,9 +179,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingGetTotalShards(uuid: UUID): Int = blockingGetShardTypeShards(uuid, ShardType.TOTAL) @@ -190,9 +190,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * lock applied this function will wait until its released * * @throws DiamondBankException.EconomyDisabledException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, Exception::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun blockingGetAllShards(uuid: UUID): PlayerShards { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -200,12 +200,20 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { val result = postgreSQL.getAllShards(uuid) - result.exceptionOrNull()?.let { throw it } + result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } result.getOrThrow() } } } + /** + * WARNING: do not run on a thread where blocking is unacceptable WARNING: blocking, if the player has a transaction + * lock applied this function will wait until its released + * + * @throws DiamondBankException.EconomyDisabledException + * @throws DiamondBankException.DatabaseException + */ + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) private fun blockingGetShardTypeShards(uuid: UUID, type: ShardType): Int { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -219,7 +227,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } - result.exceptionOrNull()?.let { throw it } + result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } result.getOrThrow() } } @@ -229,12 +237,12 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.TransactionsLockedException::class, - Exception::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun getBankShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.BANK) @@ -244,12 +252,12 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.TransactionsLockedException::class, - Exception::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun getInventoryShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.INVENTORY) @@ -259,12 +267,12 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.TransactionsLockedException::class, - Exception::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun getEnderChestShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.ENDER_CHEST) @@ -274,12 +282,12 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.TransactionsLockedException::class, - Exception::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun getTotalShards(uuid: UUID): Int = getShardTypeShards(uuid, ShardType.TOTAL) @@ -289,8 +297,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.TransactionsLockedException - * @throws java.lang.Exception + * @throws DiamondBankException.DatabaseException */ + @Throws( + DiamondBankException.EconomyDisabledException::class, + DiamondBankException.TransactionsLockedException::class, + DiamondBankException.DatabaseException::class, + ) @Suppress("unused") fun getAllShards(uuid: UUID): PlayerShards { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -300,7 +313,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } ) { is LockResult.Acquired -> { - result.result.exceptionOrNull()?.let { throw it } + result.result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } result.result.getOrThrow() } @@ -325,7 +338,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } ) { is LockResult.Acquired -> { - result.result.exceptionOrNull()?.let { throw it } + result.result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } result.result.getOrThrow() } @@ -338,9 +351,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * WARNING: do not run on a thread where blocking is unacceptable * * @throws DiamondBankException.EconomyDisabledException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ - @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.OtherException::class) + @Throws(DiamondBankException.EconomyDisabledException::class, DiamondBankException.DatabaseException::class) @Suppress("unused") fun getBaltop(offset: Int): CompletableFuture> { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException @@ -348,7 +361,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { return DiamondBankOG.scope.future { val baltop = postgreSQL.getBaltop(offset) if (baltop == null) { - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException("Database exception") } baltop } @@ -363,13 +376,13 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.InvalidPlayerException * @throws DiamondBankException.PlayerNotOnlineException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.InvalidPlayerException::class, DiamondBankException.PlayerNotOnlineException::class, - DiamondBankException.OtherException::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun blockingWithdrawFromPlayer( @@ -390,7 +403,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val notRemoved = WithdrawHelper.withdrawFromPlayer(playerPlayer, shards) if (notRemoved != 0) { handleError(uuid, shards, null) - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException("Database exception") } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -409,14 +422,14 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.InvalidPlayerException * @throws DiamondBankException.PlayerNotOnlineException * @throws DiamondBankException.TransactionsLockedException - * @throws DiamondBankException.OtherException + * @throws DiamondBankException.DatabaseException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.InvalidPlayerException::class, DiamondBankException.PlayerNotOnlineException::class, DiamondBankException.TransactionsLockedException::class, - DiamondBankException.OtherException::class, + DiamondBankException.DatabaseException::class, ) @Suppress("unused") fun withdrawFromPlayer( @@ -439,7 +452,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val notRemoved = WithdrawHelper.withdrawFromPlayer(playerPlayer, shards) if (notRemoved != 0) { handleError(uuid, shards, null) - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException("Database exception") } DiamondBankOG.postgreSQL @@ -463,12 +476,14 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.EconomyDisabledException * @throws DiamondBankException.InvalidPlayerException * @throws DiamondBankException.PlayerNotOnlineException + * @throws DiamondBankException.DatabaseException * @throws DiamondBankException.OtherException */ @Throws( DiamondBankException.EconomyDisabledException::class, DiamondBankException.InvalidPlayerException::class, DiamondBankException.PlayerNotOnlineException::class, + DiamondBankException.DatabaseException::class, DiamondBankException.OtherException::class, ) @Suppress("unused") @@ -499,7 +514,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL @@ -518,6 +533,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { * @throws DiamondBankException.InvalidPlayerException * @throws DiamondBankException.PlayerNotOnlineException * @throws DiamondBankException.TransactionsLockedException + * @throws DiamondBankException.DatabaseException * @throws DiamondBankException.OtherException */ @Throws( @@ -525,6 +541,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { DiamondBankException.InvalidPlayerException::class, DiamondBankException.PlayerNotOnlineException::class, DiamondBankException.TransactionsLockedException::class, + DiamondBankException.DatabaseException::class, DiamondBankException.OtherException::class, ) @Suppress("unused") @@ -557,7 +574,7 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - throw DiamondBankException.OtherException + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } DiamondBankOG.postgreSQL diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt index 2b295ac..1613ca9 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt @@ -26,7 +26,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - return@withLockSuspend Result.failure(DiamondBankException.OtherException) + return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -54,7 +54,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) + return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL @@ -87,7 +87,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return DiamondBankOG.transactionLock.withLockSuspend(uuid) { postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { - return@withLockSuspend Result.failure(DiamondBankException.OtherException) + return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -115,7 +115,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { - return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) + return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL @@ -160,12 +160,16 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { - when (type) { + val result = when (type) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } + result.exceptionOrNull()?.let { + Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + } + Result.success(result.getOrThrow()) } } @@ -182,7 +186,13 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return when ( - val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } + val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { + val result = postgreSQL.getAllShards(uuid) + result.exceptionOrNull()?.let { + Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + } + Result.success(result.getOrThrow()) + } ) { is LockResult.Acquired -> result.result @@ -196,12 +206,16 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - when (type) { + val result = when (type) { ShardType.BANK -> postgreSQL.getBankShards(uuid) ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } + result.exceptionOrNull()?.let { + Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + } + Result.success(result.getOrThrow()) } ) { is LockResult.Acquired -> result.result @@ -216,7 +230,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { val baltop = postgreSQL.getBaltop(offset) if (baltop == null) { - return Result.failure(DiamondBankException.OtherException) + return Result.failure(DiamondBankException.DatabaseException("Database exception")) } return Result.success(baltop) } @@ -333,7 +347,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - return@withLockSuspend Result.failure(DiamondBankException.OtherException) + return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL @@ -382,7 +396,7 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - return@tryWithLockSuspend Result.failure(DiamondBankException.OtherException) + return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } DiamondBankOG.postgreSQL diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankException.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankException.kt index 75c32e6..b319762 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankException.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankException.kt @@ -21,6 +21,8 @@ sealed class DiamondBankException(message: String) : Exception(message) { @Suppress("unused") private fun readResolve(): Any = PlayerNotOnlineException } + class DatabaseException(message: String) : DiamondBankException(message) + object OtherException : DiamondBankException("Other exception") { @Suppress("unused") private fun readResolve(): Any = OtherException } -- 2.47.3 From 59b60432dac201ac040eeed75b396ff6e87e54e5 Mon Sep 17 00:00:00 2001 From: Sven Date: Sun, 20 Jul 2025 15:21:30 +0200 Subject: [PATCH 8/8] Make all PostgreSQL function use Result --- .../diamondbankog/DiamondBankAPIJava.kt | 28 +++++--- .../diamondbankog/DiamondBankAPIKotlin.kt | 71 +++++++++++-------- .../net/trueog/diamondbankog/PostgreSQL.kt | 35 +++++---- .../diamondbankog/commands/Balancetop.kt | 50 ++++++------- 4 files changed, 109 insertions(+), 75 deletions(-) diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt index cc78744..6687a24 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIJava.kt @@ -94,7 +94,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { - postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } + postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { handleError(uuid, shards, null, null, true) @@ -200,7 +202,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { return runBlocking { DiamondBankOG.transactionLock.withLockSuspend(uuid) { val result = postgreSQL.getAllShards(uuid) - result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } + result.exceptionOrNull()?.let { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } result.getOrThrow() } } @@ -227,7 +231,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) } } - result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } + result.exceptionOrNull()?.let { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } result.getOrThrow() } } @@ -313,7 +319,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.getAllShards(uuid) } ) { is LockResult.Acquired -> { - result.result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } + result.result.exceptionOrNull()?.let { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } result.result.getOrThrow() } @@ -338,7 +346,9 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { } ) { is LockResult.Acquired -> { - result.result.exceptionOrNull()?.let { throw DiamondBankException.DatabaseException(it.message ?: "Database exception") } + result.result.exceptionOrNull()?.let { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } result.result.getOrThrow() } @@ -359,10 +369,10 @@ class DiamondBankAPIJava(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) throw DiamondBankException.EconomyDisabledException return DiamondBankOG.scope.future { - val baltop = postgreSQL.getBaltop(offset) - if (baltop == null) { - throw DiamondBankException.DatabaseException("Database exception") - } + val baltop = + postgreSQL.getBaltop(offset).getOrElse { + throw DiamondBankException.DatabaseException(it.message ?: "Database exception") + } baltop } } diff --git a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt index 1613ca9..f80c10a 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/DiamondBankAPIKotlin.kt @@ -26,7 +26,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@withLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -54,7 +56,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.addToPlayerShards(uuid, shards, ShardType.BANK).getOrElse { - return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@tryWithLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL @@ -87,7 +91,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return DiamondBankOG.transactionLock.withLockSuspend(uuid) { postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { - return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@withLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL.insertTransactionLog(uuid, shards, null, transactionReason, notes).getOrElse { @@ -115,7 +121,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { postgreSQL.subtractFromBankShards(uuid, shards).getOrElse { - return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@tryWithLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL @@ -160,12 +168,13 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return DiamondBankOG.transactionLock.withLockSuspend(uuid) { - val result = when (type) { - ShardType.BANK -> postgreSQL.getBankShards(uuid) - ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) - ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) - } + val result = + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) + } result.exceptionOrNull()?.let { Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } @@ -186,13 +195,14 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) return when ( - val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val result = postgreSQL.getAllShards(uuid) - result.exceptionOrNull()?.let { - Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + val result = + DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { + val result = postgreSQL.getAllShards(uuid) + result.exceptionOrNull()?.let { + Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + } + Result.success(result.getOrThrow()) } - Result.success(result.getOrThrow()) - } ) { is LockResult.Acquired -> result.result @@ -206,12 +216,13 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { return when ( val result = DiamondBankOG.transactionLock.tryWithLockSuspend(uuid) { - val result = when (type) { - ShardType.BANK -> postgreSQL.getBankShards(uuid) - ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) - ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) - ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) - } + val result = + when (type) { + ShardType.BANK -> postgreSQL.getBankShards(uuid) + ShardType.INVENTORY -> postgreSQL.getInventoryShards(uuid) + ShardType.ENDER_CHEST -> postgreSQL.getEnderChestShards(uuid) + ShardType.TOTAL -> postgreSQL.getTotalShards(uuid) + } result.exceptionOrNull()?.let { Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) } @@ -228,10 +239,10 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { suspend fun getBaltop(offset: Int): Result> { if (DiamondBankOG.economyDisabled) return Result.failure(DiamondBankException.EconomyDisabledException) - val baltop = postgreSQL.getBaltop(offset) - if (baltop == null) { - return Result.failure(DiamondBankException.DatabaseException("Database exception")) - } + val baltop = + postgreSQL.getBaltop(offset).getOrElse { + return Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + } return Result.success(baltop) } @@ -347,7 +358,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - return@withLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@withLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL @@ -396,7 +409,9 @@ class DiamondBankAPIKotlin(private var postgreSQL: PostgreSQL) { postgreSQL.addToPlayerShards(receiver.uniqueId, shards, ShardType.BANK).getOrElse { handleError(sender.uniqueId, shards, null) - return@tryWithLockSuspend Result.failure(DiamondBankException.DatabaseException(it.message ?: "Database exception")) + return@tryWithLockSuspend Result.failure( + DiamondBankException.DatabaseException(it.message ?: "Database exception") + ) } DiamondBankOG.postgreSQL diff --git a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt index f89c53b..5b09f44 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/PostgreSQL.kt @@ -12,7 +12,13 @@ import kotlinx.coroutines.future.await class PostgreSQL { lateinit var pool: ConnectionPool - class InvalidArgumentException : Exception() + object InvalidArgumentException : Exception() { + @Suppress("unused") private fun readResolve(): Any = InvalidArgumentException + } + + object NoRowsException : Exception() { + @Suppress("unused") private fun readResolve(): Any = NoRowsException + } enum class ShardType(val string: String) { BANK("bank_shards"), @@ -83,7 +89,7 @@ class PostgreSQL { data class PlayerShards(val bank: Int, val inventory: Int, val enderChest: Int) suspend fun setPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { - if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException()) + if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException) try { val connection = pool.asSuspending.connect() @@ -100,7 +106,7 @@ class PostgreSQL { } suspend fun addToPlayerShards(uuid: UUID, shards: Int, type: ShardType): Result { - if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException()) + if (type == ShardType.TOTAL) return Result.failure(InvalidArgumentException) val playerShards = when (type) { @@ -108,7 +114,7 @@ class PostgreSQL { ShardType.INVENTORY -> getInventoryShards(uuid) ShardType.ENDER_CHEST -> getEnderChestShards(uuid) else -> { - return Result.failure(InvalidArgumentException()) + return Result.failure(InvalidArgumentException) } } @@ -244,7 +250,7 @@ class PostgreSQL { return Result.success(shards) } - suspend fun getBaltop(offset: Int): Map? { + suspend fun getBaltop(offset: Int): Result> { try { val connection = pool.asSuspending.connect() val preparedStatement = @@ -269,18 +275,18 @@ class PostgreSQL { baltop[uuid] = totalShards } - return baltop + return Result.success(baltop) } catch (e: Exception) { DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) } - return null } /** * @return Pair with as the first value a map with the player name and total balance and as the second value the * offset */ - suspend fun getBaltopWithUuid(uuid: UUID): Pair, Long>? { + suspend fun getBaltopWithUuid(uuid: UUID): Result, Long>> { try { val connection = pool.asSuspending.connect() // @formatter:off @@ -322,15 +328,15 @@ class PostgreSQL { baltop[uuid] = totalShards } - return Pair(baltop, offset) + return Result.success(Pair(baltop, offset)) } catch (e: Exception) { DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) } - return null } - suspend fun getNumberOfRows(): Long? { - var number: Long? = null + suspend fun getNumberOfRows(): Result { + var number: Long? try { val connection = pool.asSuspending.connect() val preparedStatement = @@ -343,11 +349,14 @@ class PostgreSQL { if (rowData.columns[0] != null) { rowData.columns[0] as Long } else 0 + } else { + return Result.failure(NoRowsException) } + return Result.success(number) } catch (e: Exception) { DiamondBankOG.plugin.logger.severe(e.toString()) + return Result.failure(e) } - return number } suspend fun insertTransactionLog( diff --git a/src/main/kotlin/net/trueog/diamondbankog/commands/Balancetop.kt b/src/main/kotlin/net/trueog/diamondbankog/commands/Balancetop.kt index c0da8df..44ef128 100644 --- a/src/main/kotlin/net/trueog/diamondbankog/commands/Balancetop.kt +++ b/src/main/kotlin/net/trueog/diamondbankog/commands/Balancetop.kt @@ -73,16 +73,15 @@ internal class Balancetop : CommandExecutor { } if (player != null) { - val baltopWithUuid = DiamondBankOG.postgreSQL.getBaltopWithUuid(player.uniqueId) - if (baltopWithUuid == null) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + val baltopWithUuid = + DiamondBankOG.postgreSQL.getBaltopWithUuid(player.uniqueId).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + ) ) - ) - return@launch - } - + return@launch + } val (baltop, offset) = baltopWithUuid var baltopMessage = "${Config.prefix} Top Balances:" @@ -112,24 +111,25 @@ internal class Balancetop : CommandExecutor { return@launch } - val baltop = DiamondBankOG.postgreSQL.getBaltop(offset) - if (baltop == null) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + val baltop = + DiamondBankOG.postgreSQL.getBaltop(offset).getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + ) ) - ) - return@launch - } - val numberOfRows = DiamondBankOG.postgreSQL.getNumberOfRows() - if (numberOfRows == null) { - sender.sendMessage( - DiamondBankOG.mm.deserialize( - "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + return@launch + } + + val numberOfRows = + DiamondBankOG.postgreSQL.getNumberOfRows().getOrElse { + sender.sendMessage( + DiamondBankOG.mm.deserialize( + "${Config.prefix}: Something went wrong while trying to get the information for balancetop." + ) ) - ) - return@launch - } + return@launch + } if (index > ceil(numberOfRows / 9.0)) { sender.sendMessage( -- 2.47.3