feat(coordinator): add Redis integration and improve configuration for game state management
Build & Test (NowChessSystems) TeamCity build was removed from queue

This commit is contained in:
2026-04-26 18:25:03 +02:00
parent f327441089
commit 106b4d3b7e
56 changed files with 1072 additions and 1139 deletions
@@ -0,0 +1,32 @@
quarkus:
application.name: nowchess-store
http.port: 8085
config.yaml.enabled: true
datasource:
db-kind: postgresql
username: ${DB_USER:nowchess}
password: ${DB_PASSWORD:nowchess}
jdbc.url: ${DB_URL:jdbc:postgresql://localhost:5432/nowchess}
hibernate-orm:
database.generation: update
nowchess:
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}
prefix: ${REDIS_PREFIX:nowchess}
"%test":
quarkus:
datasource:
db-kind: h2
username: sa
password: ""
jdbc.url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
hibernate-orm:
database.generation: drop-and-create
nowchess:
redis:
host: localhost
port: 6379
prefix: test-store
@@ -18,7 +18,8 @@ class RedissonProducer:
@ApplicationScoped
def redissonClient(): RedissonClient =
val config = new Config()
config.useSingleServer()
config
.useSingleServer()
.setAddress(s"redis://${redisConfig.host}:${redisConfig.port}")
.setConnectionMinimumIdleSize(1)
.setConnectTimeout(500)
@@ -1,24 +1,24 @@
package de.nowchess.store.redis
case class GameWritebackEventDto(
gameId: String,
fen: String,
pgn: String,
moveCount: Int,
whiteId: String,
whiteName: String,
blackId: String,
blackName: String,
mode: String,
resigned: Boolean,
limitSeconds: Option[Int],
incrementSeconds: Option[Int],
daysPerMove: Option[Int],
whiteRemainingMs: Option[Long],
blackRemainingMs: Option[Long],
incrementMs: Option[Long],
clockLastTickAt: Option[Long],
clockMoveDeadline: Option[Long],
clockActiveColor: Option[String],
pendingDrawOffer: Option[String],
gameId: String,
fen: String,
pgn: String,
moveCount: Int,
whiteId: String,
whiteName: String,
blackId: String,
blackName: String,
mode: String,
resigned: Boolean,
limitSeconds: Option[Int],
incrementSeconds: Option[Int],
daysPerMove: Option[Int],
whiteRemainingMs: Option[Long],
blackRemainingMs: Option[Long],
incrementMs: Option[Long],
clockLastTickAt: Option[Long],
clockMoveDeadline: Option[Long],
clockActiveColor: Option[String],
pendingDrawOffer: Option[String],
)
@@ -14,17 +14,18 @@ import scala.util.Try
class GameWritebackStreamListener:
@Inject
// scalafix:off DisableSyntax.var
var redisson: RedissonClient = uninitialized
@Inject var objectMapper: ObjectMapper = uninitialized
var redisson: RedissonClient = uninitialized
@Inject var objectMapper: ObjectMapper = uninitialized
@Inject var writebackService: GameWritebackService = uninitialized
// scalafix:on
@PostConstruct
def startListening(): Unit =
val topic = redisson.getTopic("game-writeback")
topic.addListener(classOf[String], new MessageListener[String]:
def onMessage(channel: CharSequence, json: String): Unit =
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto]))
.toOption
.foreach(writebackService.writeBack)
topic.addListener(
classOf[String],
new MessageListener[String]:
def onMessage(channel: CharSequence, json: String): Unit =
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])).toOption
.foreach(writebackService.writeBack),
)
@@ -19,5 +19,6 @@ class StoreGameResource:
@Path("/{gameId}")
@Produces(Array(MediaType.APPLICATION_JSON))
def getGame(@PathParam("gameId") gameId: String): Response =
repository.findByGameId(gameId)
repository
.findByGameId(gameId)
.fold(Response.status(404).build())(r => Response.ok(r).build())