forked from SteamWar/SteamWar
Restore BauweltMember cache and notify all dev servers on member changes
getBauMember never read its cache after the Exposed migration, so every scoreboard render hit the DB (Too many connections, #479). Cache by (bauwelt, member) incl. negative results, evict on addMember/remove, and send BaumemberUpdatePacket to the Bauserver and all dev servers (also on addmember). BauMemberUpdate clears the cache itself to not depend on handler order.
This commit is contained in:
@@ -30,6 +30,7 @@ import org.jetbrains.exposed.v1.dao.CompositeEntity
|
||||
import org.jetbrains.exposed.v1.dao.CompositeEntityClass
|
||||
import org.jetbrains.exposed.v1.jdbc.insertIgnore
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
object BauweltMemberTable : CompositeIdTable("BauweltMember") {
|
||||
val bauweltId = reference("BauweltID", SteamwarUserTable).index()
|
||||
@@ -48,10 +49,12 @@ object BauweltMemberTable : CompositeIdTable("BauweltMember") {
|
||||
|
||||
class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||
companion object : CompositeEntityClass<BauweltMember>(BauweltMemberTable) {
|
||||
private val cache = mutableMapOf<Int, BauweltMember>()
|
||||
// Keyed by (bauweltId, memberId). Optional.empty() caches "is not a member", which is the
|
||||
// common case for spectators and would otherwise hit the DB on every permission check.
|
||||
private val cache = ConcurrentHashMap<Pair<Int, Int>, Optional<BauweltMember>>()
|
||||
|
||||
private fun cache(member: BauweltMember) =
|
||||
cache.put(member.memberID, member)
|
||||
cache.put(member.bauweltID to member.memberID, Optional.of(member))
|
||||
|
||||
@JvmStatic
|
||||
fun clear() =
|
||||
@@ -75,20 +78,20 @@ class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||
it[worldEdit] = false
|
||||
it[world] = false
|
||||
}
|
||||
}
|
||||
}.also { cache.remove(ownerId.value to newMemberId.value) }
|
||||
|
||||
@JvmStatic
|
||||
@Deprecated("Use getBauMember(bauwelt: Int, member: Int)")
|
||||
fun getBauMember(bauwelt: UUID, member: UUID) =
|
||||
useDb {
|
||||
find { (bauweltId eq SteamwarUser.get(bauwelt)!!.id) and (BauweltMemberTable.memberId eq SteamwarUser.get(member)!!.id) }.firstOrNull()?.also { cache(it) }
|
||||
}
|
||||
getBauMember(SteamwarUser.get(bauwelt)!!.id.value, SteamwarUser.get(member)!!.id.value)
|
||||
|
||||
@JvmStatic
|
||||
fun getBauMember(bauwelt: Int, member: Int) =
|
||||
useDb {
|
||||
find { (bauweltId eq bauwelt) and (BauweltMemberTable.memberId eq member) }.firstOrNull()?.also { cache(it) }
|
||||
}
|
||||
fun getBauMember(bauwelt: Int, member: Int): BauweltMember? =
|
||||
cache.computeIfAbsent(bauwelt to member) {
|
||||
Optional.ofNullable(useDb {
|
||||
find { (bauweltId eq bauwelt) and (BauweltMemberTable.memberId eq member) }.firstOrNull()
|
||||
})
|
||||
}.orElse(null)
|
||||
|
||||
@JvmStatic
|
||||
@Deprecated("Use getMembers(bauwelt: Int)")
|
||||
@@ -140,8 +143,11 @@ class BauweltMember(id: EntityID<CompositeID>) : CompositeEntity(id) {
|
||||
fun isWorld() =
|
||||
world
|
||||
|
||||
fun remove() =
|
||||
fun remove() {
|
||||
val key = bauweltID to memberID
|
||||
useDb {
|
||||
delete()
|
||||
}
|
||||
cache.remove(key)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user