Prevent deadlock in internalAddToPlayerShards by introducing internalGetShardTypeShards

This commit is contained in:
SKBotNL committed 2026-09-17 23:25:12 +02:00
1 parent 232e663387
commit 85d104269f
2 files changed
+22 -8

No files matched your search

@@ -35,7 +35,8 @@ class DiamondBankAPIKotlin {
return transactionLock.withLockSuspend(uuid) {
val player = Bukkit.getPlayer(uuid) ?: Bukkit.getOfflinePlayer(uuid)
if (player !is Player && !player.hasPlayedBefore()) return@withLockSuspend Result.failure(InvalidPlayerException())
if (player !is Player && !player.hasPlayedBefore())
return@withLockSuspend Result.failure(InvalidPlayerException())
balanceManager.addToBankShards(uuid, shards.toLong()).getOrElse {
handleError(it)
@@ -68,7 +69,8 @@ class DiamondBankAPIKotlin {
return transactionLock.withLockSuspend(uuid) {
val player = Bukkit.getPlayer(uuid) ?: Bukkit.getOfflinePlayer(uuid)
if (player !is Player && !player.hasPlayedBefore()) return@withLockSuspend Result.failure(InvalidPlayerException())
if (player !is Player && !player.hasPlayedBefore())
return@withLockSuspend Result.failure(InvalidPlayerException())
balanceManager.subtractFromBankShards(uuid, shards.toLong()).getOrElse {
if (it is InsufficientBalanceException) return@withLockSuspend Result.failure(it)
@@ -161,7 +163,8 @@ class DiamondBankAPIKotlin {
return transactionLock.withLockSuspend(uuid) {
val player = Bukkit.getOfflinePlayer(uuid)
if (player !is Player && !player.hasPlayedBefore()) return@withLockSuspend Result.failure(InvalidPlayerException())
if (player !is Player && !player.hasPlayedBefore())
return@withLockSuspend Result.failure(InvalidPlayerException())
player.uniqueId
.withInventoryLockSuspend {
@@ -220,10 +223,12 @@ class DiamondBankAPIKotlin {
return transactionLock.withLockSuspend(senderUuid) {
val sender = Bukkit.getPlayer(senderUuid) ?: Bukkit.getOfflinePlayer(senderUuid)
if (sender !is Player && !sender.hasPlayedBefore()) return@withLockSuspend Result.failure(InvalidPlayerException())
if (sender !is Player && !sender.hasPlayedBefore())
return@withLockSuspend Result.failure(InvalidPlayerException())
val receiver = Bukkit.getPlayer(receiverUuid) ?: Bukkit.getOfflinePlayer(receiverUuid)
if (receiver !is Player && !receiver.hasPlayedBefore()) return@withLockSuspend Result.failure(InvalidPlayerException())
if (receiver !is Player && !receiver.hasPlayedBefore())
return@withLockSuspend Result.failure(InvalidPlayerException())
sender.uniqueId
.withInventoryLockSuspend {
@@ -139,7 +139,7 @@ internal class PostgreSQL private constructor() {
.await()
if (result.rows.isEmpty()) {
val shards = getShardTypeShards(uuid, type).getOrElse { throw it }
val shards = internalGetShardTypeShards(uuid, type, conn).getOrElse { throw it }
throw InsufficientBalanceException(shards)
}
val row = result.rows[0]
@@ -271,12 +271,21 @@ internal class PostgreSQL private constructor() {
}
suspend fun getShardTypeShards(uuid: UUID, type: ShardType): Result<Long> {
var shards: Long?
try {
val connection = pool.asSuspending.connect()
return internalGetShardTypeShards(uuid, type, connection)
} catch (e: Exception) {
plugin.logger.severe(e.toString())
return Result.failure(DatabaseException(e.message ?: "Database exception"))
}
}
private suspend fun internalGetShardTypeShards(uuid: UUID, type: ShardType, conn: Connection): Result<Long> {
var shards: Long?
try {
val result =
connection
conn
.inTransaction { conn ->
conn.sendPreparedStatement(
"SELECT ${type.string} FROM diamond WHERE uuid = ? LIMIT 1",