feat(redis): migrate from Redisson to Quarkus Redis client and update configuration

This commit is contained in:
2026-04-28 22:44:10 +02:00
parent 0652dd2d2f
commit 5d97c3c8b5
58 changed files with 209 additions and 504 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ dependencies {
implementation("io.quarkus:quarkus-rest-client")
implementation("io.quarkus:quarkus-rest-client-jackson")
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
implementation("org.redisson:redisson:${versions["REDISSON"]!!}")
implementation("io.quarkus:quarkus-redis-client")
implementation("io.fabric8:kubernetes-client:6.13.0")
testImplementation(platform("org.junit:junit-bom:${versions["JUNIT_BOM"]!!}"))
@@ -3,6 +3,8 @@ quarkus:
name: nowchess-coordinator
http:
port: 8086
redis:
hosts: redis://${REDIS_HOST:localhost}:${REDIS_PORT:6379}
grpc:
server:
port: 9086
@@ -4,29 +4,9 @@ import jakarta.enterprise.context.ApplicationScoped
import jakarta.enterprise.inject.Produces
import io.fabric8.kubernetes.client.KubernetesClientBuilder
import io.fabric8.kubernetes.client.KubernetesClient
import org.redisson.Redisson
import org.redisson.api.RedissonClient
import org.redisson.config.Config
import org.eclipse.microprofile.config.inject.ConfigProperty
import jakarta.inject.Inject
import scala.compiletime.uninitialized
@ApplicationScoped
class BeansProducer:
@Inject
@ConfigProperty(name = "nowchess.redis.host", defaultValue = "localhost")
private var redisHost: String = uninitialized
@Inject
@ConfigProperty(name = "nowchess.redis.port", defaultValue = "6379")
private var redisPort: Int = uninitialized
@Produces
@ApplicationScoped
def redissonClient: RedissonClient =
val config = Config()
config.useSingleServer().setAddress(s"redis://$redisHost:$redisPort")
Redisson.create(config)
@Produces
@ApplicationScoped
@@ -2,7 +2,7 @@ package de.nowchess.coordinator.service
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import org.redisson.api.RedissonClient
import io.quarkus.redis.datasource.RedisDataSource
import de.nowchess.coordinator.config.CoordinatorConfig
import com.fasterxml.jackson.databind.ObjectMapper
import scala.jdk.CollectionConverters.*
@@ -15,7 +15,7 @@ import de.nowchess.coordinator.grpc.CoreGrpcClient
@ApplicationScoped
class CacheEvictionManager:
@Inject
private var redissonClient: RedissonClient = uninitialized
private var redis: RedisDataSource = uninitialized
@Inject
private var config: CoordinatorConfig = uninitialized
@@ -39,7 +39,7 @@ class CacheEvictionManager:
log.info("Starting cache eviction scan")
val pattern = s"$redisPrefix:game:entry:*"
val keys = redissonClient.getKeys.getKeysByPattern(pattern, 100)
val keys = redis.key(classOf[String]).keys(pattern)
val now = System.currentTimeMillis()
val idleThresholdMs = config.gameIdleThreshold.toMillis
@@ -47,8 +47,7 @@ class CacheEvictionManager:
var evictedCount = 0
keys.asScala.foreach { key =>
try
val bucket = redissonClient.getBucket[String](key)
val value = bucket.get()
val value = redis.value(classOf[String]).get(key)
if value != null then
val gameId = key.stripPrefix(s"$redisPrefix:game:entry:")
val lastUpdated = extractLastUpdatedTimestamp(value)
@@ -57,7 +56,7 @@ class CacheEvictionManager:
findInstanceWithGame(gameId).foreach { instance =>
try
coreGrpcClient.evictGames(instance.hostname, instance.grpcPort, List(gameId))
bucket.delete()
redis.key(classOf[String]).del(key)
evictedCount += 1
log.infof("Evicted idle game %s from %s", gameId, instance.instanceId)
catch
@@ -82,9 +81,8 @@ class CacheEvictionManager:
private def findInstanceWithGame(gameId: String): Option[de.nowchess.coordinator.dto.InstanceMetadata] =
try
instanceRegistry.getAllInstances.find { instance =>
val setKey = s"$redisPrefix:instance:${instance.instanceId}:games"
val gameSet = redissonClient.getSet[String](setKey)
gameSet.contains(gameId)
val setKey = s"$redisPrefix:instance:${instance.instanceId}:games"
redis.set(classOf[String]).sismember(setKey, gameId)
}
catch
case ex: Exception =>
@@ -2,7 +2,7 @@ package de.nowchess.coordinator.service
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import org.redisson.api.RedissonClient
import io.quarkus.redis.datasource.RedisDataSource
import scala.jdk.CollectionConverters.*
import scala.compiletime.uninitialized
import org.jboss.logging.Logger
@@ -12,7 +12,7 @@ import de.nowchess.coordinator.grpc.CoreGrpcClient
@ApplicationScoped
class FailoverService:
@Inject
private var redissonClient: RedissonClient = uninitialized
private var redis: RedisDataSource = uninitialized
@Inject
private var instanceRegistry: InstanceRegistry = uninitialized
@@ -50,9 +50,8 @@ class FailoverService:
cleanupDeadInstance(instanceId)
private def getOrphanedGames(instanceId: String): List[String] =
val setKey = s"$redisPrefix:instance:$instanceId:games"
val gameSet = redissonClient.getSet[String](setKey)
gameSet.readAll.asScala.toList
val setKey = s"$redisPrefix:instance:$instanceId:games"
redis.set(classOf[String]).smembers(setKey).asScala.toList
private def distributeGames(
gameIds: List[String],
@@ -87,7 +86,6 @@ class FailoverService:
}
private def cleanupDeadInstance(instanceId: String): Unit =
val setKey = s"$redisPrefix:instance:$instanceId:games"
val gameSet = redissonClient.getSet[String](setKey)
gameSet.delete()
val setKey = s"$redisPrefix:instance:$instanceId:games"
redis.key(classOf[String]).del(setKey)
log.infof("Cleaned up games set for instance %s", instanceId)
@@ -5,7 +5,7 @@ import jakarta.inject.Inject
import de.nowchess.coordinator.config.CoordinatorConfig
import io.fabric8.kubernetes.client.KubernetesClient
import io.fabric8.kubernetes.api.model.Pod
import org.redisson.api.RedissonClient
import io.quarkus.redis.datasource.RedisDataSource
import scala.jdk.CollectionConverters.*
import org.jboss.logging.Logger
import scala.compiletime.uninitialized
@@ -23,7 +23,7 @@ class HealthMonitor:
private var instanceRegistry: InstanceRegistry = uninitialized
@Inject
private var redissonClient: RedissonClient = uninitialized
private var redis: RedisDataSource = uninitialized
private val log = Logger.getLogger(classOf[HealthMonitor])
private var redisPrefix = "nowchess"
@@ -47,10 +47,8 @@ class HealthMonitor:
private def checkRedisHeartbeat(instanceId: String): Boolean =
try
val key = s"$redisPrefix:instances:$instanceId"
val bucket = redissonClient.getBucket[String](key)
val ttl = bucket.remainTimeToLive()
ttl > 0
val key = s"$redisPrefix:instances:$instanceId"
redis.key(classOf[String]).pttl(key) > 0
catch
case ex: Exception =>
log.debugf(ex, "Redis heartbeat check failed for %s", instanceId)
@@ -2,7 +2,7 @@ package de.nowchess.coordinator.service
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import org.redisson.api.RedissonClient
import io.quarkus.redis.datasource.RedisDataSource
import scala.jdk.CollectionConverters.*
import scala.compiletime.uninitialized
import com.fasterxml.jackson.databind.ObjectMapper
@@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap
@ApplicationScoped
class InstanceRegistry:
@Inject
private var redissonClient: RedissonClient = uninitialized
private var redis: RedisDataSource = uninitialized
private val mapper = ObjectMapper()
private val instances = ConcurrentHashMap[String, InstanceMetadata]()
@@ -28,9 +28,8 @@ class InstanceRegistry:
instances.values.asScala.toList
def updateInstanceFromRedis(instanceId: String): Unit =
val key = s"$redisPrefix:instances:$instanceId"
val bucket = redissonClient.getBucket[String](key)
val value = bucket.get()
val key = s"$redisPrefix:instances:$instanceId"
val value = redis.value(classOf[String]).get(key)
if value != null then
try
val metadata = mapper.readValue(value, classOf[InstanceMetadata])
@@ -3,7 +3,7 @@ package de.nowchess.coordinator.service
import jakarta.enterprise.context.ApplicationScoped
import jakarta.inject.Inject
import de.nowchess.coordinator.config.CoordinatorConfig
import org.redisson.api.RedissonClient
import io.quarkus.redis.datasource.RedisDataSource
import org.jboss.logging.Logger
import scala.compiletime.uninitialized
import scala.concurrent.duration.*
@@ -19,7 +19,7 @@ class LoadBalancer:
private var instanceRegistry: InstanceRegistry = uninitialized
@Inject
private var redissonClient: RedissonClient = uninitialized
private var redis: RedisDataSource = uninitialized
@Inject
private var coreGrpcClient: CoreGrpcClient = uninitialized
@@ -107,9 +107,8 @@ class LoadBalancer:
private def getGamesToMove(instanceId: String, count: Int): List[String] =
try
val setKey = s"$redisPrefix:instance:$instanceId:games"
val gameSet = redissonClient.getSet[String](setKey)
gameSet.readAll.asScala.toList.take(count)
val setKey = s"$redisPrefix:instance:$instanceId:games"
redis.set(classOf[String]).smembers(setKey).asScala.toList.take(count)
catch
case ex: Exception =>
log.debugf(ex, "Failed to get games for %s", instanceId)
@@ -120,12 +119,9 @@ class LoadBalancer:
val fromKey = s"$redisPrefix:instance:$fromInstanceId:games"
val toKey = s"$redisPrefix:instance:$toInstanceId:games"
val fromSet = redissonClient.getSet[String](fromKey)
val toSet = redissonClient.getSet[String](toKey)
gameIds.foreach { gameId =>
fromSet.remove(gameId)
toSet.add(gameId)
redis.set(classOf[String]).srem(fromKey, gameId)
redis.set(classOf[String]).sadd(toKey, gameId)
}
catch
case ex: Exception =>