Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b47ad7ef89 | |||
| 2e4ba43597 | |||
| b0d27d2de2 | |||
| 8f9eb12f66 | |||
| 5d5fffa812 | |||
| 73239088d9 | |||
| 4ad92ab236 | |||
| c65a1393b9 | |||
| 4a36096a55 | |||
| 960a419792 | |||
| 68d6c1d36f | |||
| b991878214 | |||
| 43525d41a3 | |||
| 6bf1013710 | |||
| 255e2da33c | |||
| 4b3b5e7c4e | |||
| 1d121c727c | |||
| 56f0030a83 | |||
| d0c71693bb | |||
| 3f12f695f1 | |||
| 0a3c494fa8 | |||
| f7ce4df595 | |||
| d41c03700c | |||
| 10937e756a | |||
| 380a2cceeb | |||
| 43184d296d | |||
| 67802ee1b8 | |||
| 3ed3e59ee4 | |||
| 0060229ee9 | |||
| d5c8da20f8 | |||
| ad9495afa3 | |||
| 2b04d7fa71 |
@@ -235,10 +235,10 @@
|
|||||||
- function rebalanceInterval
|
- function rebalanceInterval
|
||||||
- function rebalanceMinInterval
|
- function rebalanceMinInterval
|
||||||
- function heartbeatTtl
|
- function heartbeatTtl
|
||||||
- _...12 more_
|
- _...14 more_
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer, function hasActiveStream
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
||||||
- class CoreGrpcClient
|
- class CoreGrpcClient
|
||||||
- function shutdown
|
- function shutdown
|
||||||
@@ -256,6 +256,7 @@
|
|||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
||||||
- class AutoScaler
|
- class AutoScaler
|
||||||
- function initMetrics
|
- function initMetrics
|
||||||
|
- function periodicScaleCheck
|
||||||
- function checkAndScale
|
- function checkAndScale
|
||||||
- function scaleUp
|
- function scaleUp
|
||||||
- function scaleDown
|
- function scaleDown
|
||||||
@@ -263,6 +264,7 @@
|
|||||||
- class CacheEvictionManager
|
- class CacheEvictionManager
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function initializeMetrics
|
- function initializeMetrics
|
||||||
|
- function periodicCacheEviction
|
||||||
- function evictStaleGames
|
- function evictStaleGames
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
||||||
- class FailoverService
|
- class FailoverService
|
||||||
@@ -272,21 +274,23 @@
|
|||||||
- class HealthMonitor
|
- class HealthMonitor
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function initializeMetrics
|
- function initializeMetrics
|
||||||
|
- function onStartup
|
||||||
|
- function periodicHealthCheck
|
||||||
- function checkInstanceHealth
|
- function checkInstanceHealth
|
||||||
- function watchK8sPods
|
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
||||||
- class InstanceRegistry
|
- class InstanceRegistry
|
||||||
- function initMetrics
|
- function initMetrics
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
|
- function loadAllFromRedis
|
||||||
- function getInstance
|
- function getInstance
|
||||||
- function getAllInstances
|
- function getAllInstances
|
||||||
- function updateInstanceFromRedis
|
- _...4 more_
|
||||||
- _...3 more_
|
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
||||||
- class LoadBalancer
|
- class LoadBalancer
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function shouldRebalance
|
- function shouldRebalance
|
||||||
- function rebalance
|
- function rebalance
|
||||||
|
- function periodicRebalanceCheck
|
||||||
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
||||||
- class RuleSetRestAdapter
|
- class RuleSetRestAdapter
|
||||||
- function candidateMoves
|
- function candidateMoves
|
||||||
|
|||||||
+9
-5
@@ -179,10 +179,10 @@
|
|||||||
- function rebalanceInterval
|
- function rebalanceInterval
|
||||||
- function rebalanceMinInterval
|
- function rebalanceMinInterval
|
||||||
- function heartbeatTtl
|
- function heartbeatTtl
|
||||||
- _...12 more_
|
- _...14 more_
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/JacksonConfig.scala` — class JacksonConfig, function customize
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/config/NativeReflectionConfig.scala` — class NativeReflectionConfig
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer, function hasActiveStream
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoreGrpcClient.scala`
|
||||||
- class CoreGrpcClient
|
- class CoreGrpcClient
|
||||||
- function shutdown
|
- function shutdown
|
||||||
@@ -200,6 +200,7 @@
|
|||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/AutoScaler.scala`
|
||||||
- class AutoScaler
|
- class AutoScaler
|
||||||
- function initMetrics
|
- function initMetrics
|
||||||
|
- function periodicScaleCheck
|
||||||
- function checkAndScale
|
- function checkAndScale
|
||||||
- function scaleUp
|
- function scaleUp
|
||||||
- function scaleDown
|
- function scaleDown
|
||||||
@@ -207,6 +208,7 @@
|
|||||||
- class CacheEvictionManager
|
- class CacheEvictionManager
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function initializeMetrics
|
- function initializeMetrics
|
||||||
|
- function periodicCacheEviction
|
||||||
- function evictStaleGames
|
- function evictStaleGames
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/FailoverService.scala`
|
||||||
- class FailoverService
|
- class FailoverService
|
||||||
@@ -216,21 +218,23 @@
|
|||||||
- class HealthMonitor
|
- class HealthMonitor
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function initializeMetrics
|
- function initializeMetrics
|
||||||
|
- function onStartup
|
||||||
|
- function periodicHealthCheck
|
||||||
- function checkInstanceHealth
|
- function checkInstanceHealth
|
||||||
- function watchK8sPods
|
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/InstanceRegistry.scala`
|
||||||
- class InstanceRegistry
|
- class InstanceRegistry
|
||||||
- function initMetrics
|
- function initMetrics
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
|
- function loadAllFromRedis
|
||||||
- function getInstance
|
- function getInstance
|
||||||
- function getAllInstances
|
- function getAllInstances
|
||||||
- function updateInstanceFromRedis
|
- _...4 more_
|
||||||
- _...3 more_
|
|
||||||
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/service/LoadBalancer.scala`
|
||||||
- class LoadBalancer
|
- class LoadBalancer
|
||||||
- function setRedisPrefix
|
- function setRedisPrefix
|
||||||
- function shouldRebalance
|
- function shouldRebalance
|
||||||
- function rebalance
|
- function rebalance
|
||||||
|
- function periodicRebalanceCheck
|
||||||
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
- `modules/core/src/main/scala/de/nowchess/chess/adapter/RuleSetRestAdapter.scala`
|
||||||
- class RuleSetRestAdapter
|
- class RuleSetRestAdapter
|
||||||
- function candidateMoves
|
- function candidateMoves
|
||||||
|
|||||||
@@ -1,313 +0,0 @@
|
|||||||
# NowChess Tournament API
|
|
||||||
|
|
||||||
Swiss-system bot tournaments. Bots are paired by score each round; all bots play every round (no eliminations). Game moves flow through the existing board and bot endpoints — the tournament module only orchestrates pairings, standings, and lifecycle.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Base path
|
|
||||||
|
|
||||||
```
|
|
||||||
/api/tournament
|
|
||||||
```
|
|
||||||
|
|
||||||
Routing: `/api/tournament` → `nowchess-tournament-active:8086`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
All endpoints require a valid JWT (`Authorization: Bearer <token>`).
|
|
||||||
Bot-facing streaming endpoints additionally require the token's subject to match the registered `botId`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Data models
|
|
||||||
|
|
||||||
### Tournament
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "t7kXq2",
|
|
||||||
"name": "Friday Night Bots",
|
|
||||||
"status": "created | started | finished",
|
|
||||||
"rounds": 5,
|
|
||||||
"currentRound": 2,
|
|
||||||
"timeControl": {
|
|
||||||
"limitSeconds": 300,
|
|
||||||
"incrementSeconds": 3
|
|
||||||
},
|
|
||||||
"createdBy": "userId",
|
|
||||||
"createdAt": "2026-05-13T18:00:00Z",
|
|
||||||
"startedAt": "2026-05-13T18:05:00Z",
|
|
||||||
"finishedAt": null
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Standing
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"rank": 1,
|
|
||||||
"botId": "bot_abc",
|
|
||||||
"botName": "StockfishClone",
|
|
||||||
"points": 3.5,
|
|
||||||
"wins": 3,
|
|
||||||
"draws": 1,
|
|
||||||
"losses": 0,
|
|
||||||
"buchholz": 9.0
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Tiebreaker: Buchholz score (sum of opponents' points).
|
|
||||||
|
|
||||||
### Pairing
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"round": 2,
|
|
||||||
"whiteBot": "bot_abc",
|
|
||||||
"blackBot": "bot_xyz",
|
|
||||||
"gameId": "j0nPtcjl",
|
|
||||||
"result": "white | black | draw | ongoing"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### TournamentEvent (SSE)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "type": "tournamentStarted", "tournamentId": "t7kXq2" }
|
|
||||||
{ "type": "roundStarted", "tournamentId": "t7kXq2", "round": 2 }
|
|
||||||
{ "type": "pairingReady", "tournamentId": "t7kXq2", "round": 2, "gameId": "j0nPtcjl", "color": "white" }
|
|
||||||
{ "type": "roundFinished", "tournamentId": "t7kXq2", "round": 2 }
|
|
||||||
{ "type": "tournamentFinished","tournamentId": "t7kXq2" }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Endpoints
|
|
||||||
|
|
||||||
### Tournament lifecycle
|
|
||||||
|
|
||||||
#### Create tournament
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /api/tournament
|
|
||||||
```
|
|
||||||
|
|
||||||
Body:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Friday Night Bots",
|
|
||||||
"rounds": 5,
|
|
||||||
"timeControl": {
|
|
||||||
"limitSeconds": 300,
|
|
||||||
"incrementSeconds": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `201 Created`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "id": "t7kXq2" }
|
|
||||||
```
|
|
||||||
|
|
||||||
The creator becomes the tournament director. Only the director can start and delete the tournament.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Get tournament
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament/{tournamentId}
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `200 OK`: `Tournament` object.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### List tournaments
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament
|
|
||||||
```
|
|
||||||
|
|
||||||
Query params:
|
|
||||||
|
|
||||||
| Param | Type | Default |
|
|
||||||
|----------|---------------------------------|-----------|
|
|
||||||
| `status` | `created\|started\|finished` | (all) |
|
|
||||||
| `limit` | integer (max 50) | 20 |
|
|
||||||
| `offset` | integer | 0 |
|
|
||||||
|
|
||||||
Response `200 OK`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tournaments": [ /* Tournament[] */ ],
|
|
||||||
"total": 42
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Start tournament
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /api/tournament/{tournamentId}/start
|
|
||||||
```
|
|
||||||
|
|
||||||
Requires at least 2 registered bots. Computes round 1 pairings (random for round 1; score-based from round 2). Creates one game per pairing via `POST /api/board/game`.
|
|
||||||
|
|
||||||
Response `200 OK`: updated `Tournament` object.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Delete tournament
|
|
||||||
|
|
||||||
```
|
|
||||||
DELETE /api/tournament/{tournamentId}
|
|
||||||
```
|
|
||||||
|
|
||||||
Only allowed while `status == "created"`. Response `204 No Content`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Bot registration
|
|
||||||
|
|
||||||
#### Register bot
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /api/tournament/{tournamentId}/bots
|
|
||||||
```
|
|
||||||
|
|
||||||
Registers a bot for the tournament. Must be called before the tournament starts.
|
|
||||||
The token subject must match the bot being registered.
|
|
||||||
|
|
||||||
Body:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "botId": "bot_abc" }
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `200 OK`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "botId": "bot_abc", "tournamentId": "t7kXq2" }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Unregister bot
|
|
||||||
|
|
||||||
```
|
|
||||||
DELETE /api/tournament/{tournamentId}/bots/{botId}
|
|
||||||
```
|
|
||||||
|
|
||||||
Only allowed while `status == "created"`. Response `204 No Content`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### List registered bots
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament/{tournamentId}/bots
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `200 OK`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"bots": [
|
|
||||||
{ "botId": "bot_abc", "botName": "StockfishClone" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Standings and pairings
|
|
||||||
|
|
||||||
#### Get standings
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament/{tournamentId}/standings
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `200 OK`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "standings": [ /* Standing[] */ ] }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
#### Get pairings for a round
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament/{tournamentId}/rounds/{round}/pairings
|
|
||||||
```
|
|
||||||
|
|
||||||
Response `200 OK`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "pairings": [ /* Pairing[] */ ] }
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Bot streaming
|
|
||||||
|
|
||||||
#### Stream tournament events
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /api/tournament/{tournamentId}/stream
|
|
||||||
```
|
|
||||||
|
|
||||||
Headers: `Accept: text/event-stream`
|
|
||||||
|
|
||||||
Server-Sent Events stream scoped to this tournament. The bot receives `pairingReady` events when it is assigned a game, at which point it should connect to the existing bot game stream:
|
|
||||||
|
|
||||||
```
|
|
||||||
GET /bot/stream/game/{gameId} (existing endpoint)
|
|
||||||
POST /bot/game/{gameId}/move/{uci} (existing endpoint)
|
|
||||||
```
|
|
||||||
|
|
||||||
The tournament module never sends moves — bots do that themselves through the existing bot endpoints.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Typical bot flow
|
|
||||||
|
|
||||||
```
|
|
||||||
1. POST /api/tournament # director creates tournament
|
|
||||||
2. POST /api/tournament/{id}/bots # each bot registers
|
|
||||||
3. POST /api/tournament/{id}/start # director starts
|
|
||||||
4. GET /api/tournament/{id}/stream (SSE) # each bot opens stream
|
|
||||||
|
|
||||||
-- per round --
|
|
||||||
5. receive: pairingReady { gameId, color }
|
|
||||||
6. GET /bot/stream/game/{gameId} # existing endpoint
|
|
||||||
7. POST /bot/game/{gameId}/move/{uci} # existing endpoint, repeated
|
|
||||||
-- game ends --
|
|
||||||
|
|
||||||
8. receive: roundFinished
|
|
||||||
9. GET /api/tournament/{id}/standings # optional, inspect scores
|
|
||||||
-- repeat 5–9 for each round --
|
|
||||||
|
|
||||||
10. receive: tournamentFinished
|
|
||||||
11. GET /api/tournament/{id}/standings # final ranking
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Error responses
|
|
||||||
|
|
||||||
| Status | Meaning |
|
|
||||||
|--------|------------------------------------------------------|
|
|
||||||
| 400 | Invalid request body or parameters |
|
|
||||||
| 401 | Missing or invalid JWT |
|
|
||||||
| 403 | Action not allowed (wrong director, wrong bot, etc.) |
|
|
||||||
| 404 | Tournament or bot not found |
|
|
||||||
| 409 | Tournament already started / bot already registered |
|
|
||||||
@@ -1,623 +0,0 @@
|
|||||||
openapi: 3.0.3
|
|
||||||
info:
|
|
||||||
title: NowChess Tournament API
|
|
||||||
description: |
|
|
||||||
Swiss-system bot tournaments, modelled after the Lichess API style.
|
|
||||||
|
|
||||||
Game moves flow through the existing board and bot endpoints — this module
|
|
||||||
handles pairings, standings, and lifecycle only.
|
|
||||||
|
|
||||||
## Streaming
|
|
||||||
Endpoints marked **NDJSON** return newline-delimited JSON objects
|
|
||||||
(`application/x-ndjson`). Each line is one complete JSON object. The
|
|
||||||
connection stays open until the tournament or round ends.
|
|
||||||
|
|
||||||
## Bot flow
|
|
||||||
```
|
|
||||||
POST /api/tournament # create
|
|
||||||
POST /api/tournament/{id}/join # each bot joins
|
|
||||||
POST /api/tournament/{id}/start # director starts
|
|
||||||
|
|
||||||
GET /api/tournament/{id}/stream (NDJSON) # open before start
|
|
||||||
|
|
||||||
-- per round --
|
|
||||||
receive gameStart { gameId, color }
|
|
||||||
GET /bot/stream/game/{gameId} (existing, NDJSON)
|
|
||||||
POST /bot/game/{gameId}/move/{uci} (existing)
|
|
||||||
-- repeat --
|
|
||||||
|
|
||||||
GET /api/tournament/{id}/results (NDJSON) # final standings
|
|
||||||
```
|
|
||||||
version: 1.0.0
|
|
||||||
|
|
||||||
servers:
|
|
||||||
- url: https://st.nowchess.janis-eccarius.de
|
|
||||||
description: Staging
|
|
||||||
- url: https://nowchess.janis-eccarius.de
|
|
||||||
description: Production
|
|
||||||
- url: http://localhost:8086
|
|
||||||
description: Local
|
|
||||||
|
|
||||||
security:
|
|
||||||
- bearerAuth: []
|
|
||||||
|
|
||||||
tags:
|
|
||||||
- name: Tournament
|
|
||||||
description: Tournament lifecycle
|
|
||||||
- name: Participation
|
|
||||||
description: Join and withdraw
|
|
||||||
- name: Results
|
|
||||||
description: Standings, pairings, and game export
|
|
||||||
- name: Stream
|
|
||||||
description: NDJSON event streams
|
|
||||||
|
|
||||||
paths:
|
|
||||||
|
|
||||||
/api/tournament:
|
|
||||||
get:
|
|
||||||
tags: [Tournament]
|
|
||||||
summary: Get current tournaments
|
|
||||||
description: Returns tournaments grouped by status. No auth required.
|
|
||||||
security: []
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Tournaments by status
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
created:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/TournamentInfo"
|
|
||||||
started:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/TournamentInfo"
|
|
||||||
finished:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/TournamentInfo"
|
|
||||||
|
|
||||||
post:
|
|
||||||
tags: [Tournament]
|
|
||||||
summary: Create a new tournament
|
|
||||||
description: The authenticated user becomes the tournament director.
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/x-www-form-urlencoded:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/CreateTournamentForm"
|
|
||||||
responses:
|
|
||||||
"201":
|
|
||||||
description: Tournament created
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Tournament"
|
|
||||||
"400":
|
|
||||||
$ref: "#/components/responses/BadRequest"
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
|
|
||||||
/api/tournament/{id}:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
get:
|
|
||||||
tags: [Tournament]
|
|
||||||
summary: Get a tournament
|
|
||||||
description: Includes the first page of standings in the `standing` field.
|
|
||||||
security: []
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Tournament with embedded standings
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Tournament"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
delete:
|
|
||||||
tags: [Tournament]
|
|
||||||
summary: Terminate a tournament
|
|
||||||
description: Only the director may terminate. Only allowed while status is `created`.
|
|
||||||
responses:
|
|
||||||
"204":
|
|
||||||
description: Terminated
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
"403":
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
"409":
|
|
||||||
$ref: "#/components/responses/Conflict"
|
|
||||||
|
|
||||||
/api/tournament/{id}/start:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
post:
|
|
||||||
tags: [Tournament]
|
|
||||||
summary: Start the tournament
|
|
||||||
description: |
|
|
||||||
Only the director may start. Requires at least 2 joined bots.
|
|
||||||
Computes round 1 pairings and creates games via `POST /api/board/game`.
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Tournament started
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Tournament"
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
"403":
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
"409":
|
|
||||||
$ref: "#/components/responses/Conflict"
|
|
||||||
|
|
||||||
/api/tournament/{id}/join:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
post:
|
|
||||||
tags: [Participation]
|
|
||||||
summary: Join a tournament
|
|
||||||
description: |
|
|
||||||
Register the authenticated bot for the tournament. Only allowed while
|
|
||||||
status is `created`. The token subject must be a bot account.
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Ok
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Ok"
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
"403":
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
"409":
|
|
||||||
$ref: "#/components/responses/Conflict"
|
|
||||||
|
|
||||||
/api/tournament/{id}/withdraw:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
post:
|
|
||||||
tags: [Participation]
|
|
||||||
summary: Withdraw from a tournament
|
|
||||||
description: Only allowed while status is `created`.
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Ok
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Ok"
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
"403":
|
|
||||||
$ref: "#/components/responses/Forbidden"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
"409":
|
|
||||||
$ref: "#/components/responses/Conflict"
|
|
||||||
|
|
||||||
/api/tournament/{id}/results:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
get:
|
|
||||||
tags: [Results]
|
|
||||||
summary: Get results as NDJSON stream
|
|
||||||
description: |
|
|
||||||
Streams one `Result` object per line, sorted by rank ascending.
|
|
||||||
Available at any point during or after the tournament.
|
|
||||||
security: []
|
|
||||||
parameters:
|
|
||||||
- name: nb
|
|
||||||
in: query
|
|
||||||
description: Max number of results to stream (default all)
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
minimum: 1
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: NDJSON stream of results
|
|
||||||
content:
|
|
||||||
application/x-ndjson:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Result"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
/api/tournament/{id}/round/{round}:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
- name: round
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
minimum: 1
|
|
||||||
|
|
||||||
get:
|
|
||||||
tags: [Results]
|
|
||||||
summary: Get pairings for a round
|
|
||||||
security: []
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Pairings for the specified round
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
round:
|
|
||||||
type: integer
|
|
||||||
example: 2
|
|
||||||
pairings:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/Pairing"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
/api/tournament/{id}/export/games:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
get:
|
|
||||||
tags: [Results]
|
|
||||||
summary: Export all games
|
|
||||||
description: |
|
|
||||||
Returns all games of the tournament. Accepts both PGN and NDJSON via
|
|
||||||
the `Accept` header.
|
|
||||||
security: []
|
|
||||||
parameters:
|
|
||||||
- name: Accept
|
|
||||||
in: header
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- application/x-chess-pgn
|
|
||||||
- application/x-ndjson
|
|
||||||
default: application/x-chess-pgn
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: Games in the requested format
|
|
||||||
content:
|
|
||||||
application/x-chess-pgn:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
description: Standard PGN, one game per block
|
|
||||||
application/x-ndjson:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/GameExport"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
/api/tournament/{id}/stream:
|
|
||||||
parameters:
|
|
||||||
- $ref: "#/components/parameters/id"
|
|
||||||
|
|
||||||
get:
|
|
||||||
tags: [Stream]
|
|
||||||
summary: Stream tournament events
|
|
||||||
description: |
|
|
||||||
NDJSON stream scoped to one tournament. Keep this connection open for
|
|
||||||
the full tournament lifetime.
|
|
||||||
|
|
||||||
On `gameStart` the bot connects to the existing bot endpoints:
|
|
||||||
- `GET /bot/stream/game/{gameId}` — stream game state (existing)
|
|
||||||
- `POST /bot/game/{gameId}/move/{uci}` — submit moves (existing)
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: NDJSON event stream
|
|
||||||
content:
|
|
||||||
application/x-ndjson:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/TournamentEvent"
|
|
||||||
"401":
|
|
||||||
$ref: "#/components/responses/Unauthorized"
|
|
||||||
"404":
|
|
||||||
$ref: "#/components/responses/NotFound"
|
|
||||||
|
|
||||||
components:
|
|
||||||
|
|
||||||
securitySchemes:
|
|
||||||
bearerAuth:
|
|
||||||
type: http
|
|
||||||
scheme: bearer
|
|
||||||
bearerFormat: JWT
|
|
||||||
|
|
||||||
parameters:
|
|
||||||
id:
|
|
||||||
name: id
|
|
||||||
in: path
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
example: t7kXq2
|
|
||||||
|
|
||||||
schemas:
|
|
||||||
|
|
||||||
Clock:
|
|
||||||
type: object
|
|
||||||
required: [limit, increment]
|
|
||||||
properties:
|
|
||||||
limit:
|
|
||||||
type: integer
|
|
||||||
description: Base time in seconds
|
|
||||||
example: 300
|
|
||||||
increment:
|
|
||||||
type: integer
|
|
||||||
description: Increment per move in seconds
|
|
||||||
example: 3
|
|
||||||
|
|
||||||
Variant:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
key:
|
|
||||||
type: string
|
|
||||||
example: standard
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: Standard
|
|
||||||
|
|
||||||
BotRef:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
example: bot_abc
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: StockfishClone
|
|
||||||
|
|
||||||
Standing:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
page:
|
|
||||||
type: integer
|
|
||||||
example: 1
|
|
||||||
players:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "#/components/schemas/Result"
|
|
||||||
|
|
||||||
TournamentInfo:
|
|
||||||
description: Lightweight tournament summary used in list responses.
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
example: t7kXq2
|
|
||||||
fullName:
|
|
||||||
type: string
|
|
||||||
example: Friday Night Bots Swiss
|
|
||||||
clock:
|
|
||||||
$ref: "#/components/schemas/Clock"
|
|
||||||
variant:
|
|
||||||
$ref: "#/components/schemas/Variant"
|
|
||||||
rated:
|
|
||||||
type: boolean
|
|
||||||
example: true
|
|
||||||
nbPlayers:
|
|
||||||
type: integer
|
|
||||||
example: 8
|
|
||||||
nbRounds:
|
|
||||||
type: integer
|
|
||||||
example: 5
|
|
||||||
createdBy:
|
|
||||||
type: string
|
|
||||||
example: userId
|
|
||||||
startsAt:
|
|
||||||
type: string
|
|
||||||
format: date-time
|
|
||||||
|
|
||||||
Tournament:
|
|
||||||
allOf:
|
|
||||||
- $ref: "#/components/schemas/TournamentInfo"
|
|
||||||
- type: object
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
enum: [created, started, finished]
|
|
||||||
example: started
|
|
||||||
round:
|
|
||||||
type: integer
|
|
||||||
description: Current round number
|
|
||||||
example: 2
|
|
||||||
standing:
|
|
||||||
$ref: "#/components/schemas/Standing"
|
|
||||||
winner:
|
|
||||||
description: Present only when status is `finished`
|
|
||||||
allOf:
|
|
||||||
- $ref: "#/components/schemas/BotRef"
|
|
||||||
nullable: true
|
|
||||||
|
|
||||||
CreateTournamentForm:
|
|
||||||
type: object
|
|
||||||
required: [name, nbRounds, clockLimit, clockIncrement]
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: Friday Night Bots
|
|
||||||
nbRounds:
|
|
||||||
type: integer
|
|
||||||
minimum: 1
|
|
||||||
example: 5
|
|
||||||
clockLimit:
|
|
||||||
type: integer
|
|
||||||
description: Base time in seconds
|
|
||||||
example: 300
|
|
||||||
clockIncrement:
|
|
||||||
type: integer
|
|
||||||
description: Increment per move in seconds
|
|
||||||
example: 3
|
|
||||||
rated:
|
|
||||||
type: boolean
|
|
||||||
default: true
|
|
||||||
|
|
||||||
Result:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
rank:
|
|
||||||
type: integer
|
|
||||||
example: 1
|
|
||||||
points:
|
|
||||||
type: number
|
|
||||||
format: double
|
|
||||||
example: 3.5
|
|
||||||
tieBreak:
|
|
||||||
type: number
|
|
||||||
format: double
|
|
||||||
description: Buchholz score (sum of opponents' points)
|
|
||||||
example: 9.0
|
|
||||||
bot:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
nbGames:
|
|
||||||
type: integer
|
|
||||||
example: 4
|
|
||||||
wins:
|
|
||||||
type: integer
|
|
||||||
example: 3
|
|
||||||
draws:
|
|
||||||
type: integer
|
|
||||||
example: 1
|
|
||||||
losses:
|
|
||||||
type: integer
|
|
||||||
example: 0
|
|
||||||
|
|
||||||
Pairing:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
round:
|
|
||||||
type: integer
|
|
||||||
example: 2
|
|
||||||
white:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
black:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
gameId:
|
|
||||||
type: string
|
|
||||||
example: j0nPtcjl
|
|
||||||
winner:
|
|
||||||
type: string
|
|
||||||
enum: [white, black, draw]
|
|
||||||
nullable: true
|
|
||||||
description: Null while the game is ongoing
|
|
||||||
|
|
||||||
GameExport:
|
|
||||||
description: One game object per NDJSON line.
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
id:
|
|
||||||
type: string
|
|
||||||
example: j0nPtcjl
|
|
||||||
round:
|
|
||||||
type: integer
|
|
||||||
example: 2
|
|
||||||
white:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
black:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
winner:
|
|
||||||
type: string
|
|
||||||
enum: [white, black, draw]
|
|
||||||
nullable: true
|
|
||||||
moves:
|
|
||||||
type: string
|
|
||||||
description: Space-separated UCI moves
|
|
||||||
example: e2e4 e7e5 g1f3
|
|
||||||
|
|
||||||
TournamentEvent:
|
|
||||||
description: |
|
|
||||||
One JSON object per NDJSON line. Discriminate on `type`.
|
|
||||||
|
|
||||||
| type | extra fields |
|
|
||||||
|------|-------------|
|
|
||||||
| `tournamentStarted` | — |
|
|
||||||
| `roundStarted` | `round` |
|
|
||||||
| `gameStart` | `round`, `gameId`, `color` |
|
|
||||||
| `roundFinished` | `round` |
|
|
||||||
| `tournamentFinished` | `winner` |
|
|
||||||
type: object
|
|
||||||
required: [type]
|
|
||||||
properties:
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- tournamentStarted
|
|
||||||
- roundStarted
|
|
||||||
- gameStart
|
|
||||||
- roundFinished
|
|
||||||
- tournamentFinished
|
|
||||||
round:
|
|
||||||
type: integer
|
|
||||||
example: 2
|
|
||||||
gameId:
|
|
||||||
type: string
|
|
||||||
example: j0nPtcjl
|
|
||||||
color:
|
|
||||||
type: string
|
|
||||||
enum: [white, black]
|
|
||||||
winner:
|
|
||||||
$ref: "#/components/schemas/BotRef"
|
|
||||||
|
|
||||||
Ok:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
ok:
|
|
||||||
type: boolean
|
|
||||||
example: true
|
|
||||||
|
|
||||||
Error:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
error:
|
|
||||||
type: string
|
|
||||||
example: tournament already started
|
|
||||||
|
|
||||||
responses:
|
|
||||||
BadRequest:
|
|
||||||
description: Invalid request body or parameters
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Error"
|
|
||||||
Unauthorized:
|
|
||||||
description: Missing or invalid JWT
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Error"
|
|
||||||
Forbidden:
|
|
||||||
description: Action not permitted for this user or bot
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Error"
|
|
||||||
NotFound:
|
|
||||||
description: Tournament not found
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Error"
|
|
||||||
Conflict:
|
|
||||||
description: Conflicting state (e.g. already started, bot already joined)
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: "#/components/schemas/Error"
|
|
||||||
@@ -224,3 +224,62 @@
|
|||||||
|
|
||||||
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** add H2 database configuration for testing environment ([39c9e49](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39c9e492cef2515368c074da9406f95e9c0c9e64))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** add InternalClientHeadersFactory for custom client headers management ([e279c39](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e279c39246470156bf11e745ee72204018d4229d))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** add H2 database configuration for testing environment ([39c9e49](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39c9e492cef2515368c074da9406f95e9c0c9e64))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** add InternalClientHeadersFactory for custom client headers management ([e279c39](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e279c39246470156bf11e745ee72204018d4229d))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ nowchess:
|
|||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
http:
|
|
||||||
root-path: /api/account
|
|
||||||
log:
|
log:
|
||||||
console:
|
console:
|
||||||
json: true
|
json: true
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@ class OfficialChallengeResource:
|
|||||||
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ErrorDto(err)).build()
|
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(ErrorDto(err)).build()
|
||||||
case Right(id) =>
|
case Right(id) =>
|
||||||
try botEventPublisher.publishGameStart(bot.name, id, botColor, difficulty, bot.id.toString)
|
try botEventPublisher.publishGameStart(bot.name, id, botColor, difficulty, bot.id.toString)
|
||||||
catch case ex: Exception => log.warnf(ex, "Failed to notify bot for game %s", id)
|
catch case ex: Exception => log.errorf(ex, "Failed to notify bot for game %s", id)
|
||||||
Response
|
Response
|
||||||
.status(Response.Status.CREATED)
|
.status(Response.Status.CREATED)
|
||||||
.entity(OfficialChallengeResponse(id, botName, difficulty))
|
.entity(OfficialChallengeResponse(id, botName, difficulty))
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ class ChallengeService:
|
|||||||
challenge.expiresAt = Instant.now().plus(24, ChronoUnit.HOURS)
|
challenge.expiresAt = Instant.now().plus(24, ChronoUnit.HOURS)
|
||||||
challengeRepository.persist(challenge)
|
challengeRepository.persist(challenge)
|
||||||
try eventPublisher.publishChallengeCreated(destUser.id.toString, challenge.id.toString, challenger.username)
|
try eventPublisher.publishChallengeCreated(destUser.id.toString, challenge.id.toString, challenger.username)
|
||||||
catch case ex: Exception => log.warnf(ex, "Failed to notify dest user for challenge %s", challenge.id)
|
catch case ex: Exception => log.errorf(ex, "Failed to notify dest user for challenge %s", challenge.id)
|
||||||
challenge
|
challenge
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -116,7 +116,7 @@ class ChallengeService:
|
|||||||
challengeRepository.merge(challenge)
|
challengeRepository.merge(challenge)
|
||||||
notifyBotIfNeeded(challenge, gameId)
|
notifyBotIfNeeded(challenge, gameId)
|
||||||
try eventPublisher.publishChallengeAccepted(challenge.challenger.id.toString, challenge.id.toString, gameId)
|
try eventPublisher.publishChallengeAccepted(challenge.challenger.id.toString, challenge.id.toString, gameId)
|
||||||
catch case ex: Exception => log.warnf(ex, "Failed to notify challenger for game %s", gameId)
|
catch case ex: Exception => log.errorf(ex, "Failed to notify challenger for game %s", gameId)
|
||||||
challenge
|
challenge
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=14
|
MINOR=16
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -334,3 +334,331 @@
|
|||||||
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* scale up on high CPU load, not just subscription count ([255e2da](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/255e2da33c37e186ed14f2862f2d2e1b4adc59bf))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* don't block event loop during scale-down drain ([1d121c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1d121c727cbd4df477827cf64d065b7356a56e59))
|
||||||
|
* don't trigger scale-down if already at min replicas ([4b3b5e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4b3b5e7c4ed9b3cd4fe2490e9f268f2e3a0d9e85))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* scalafix violations in metrics check and health monitor ([b991878](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b99187821489b296d66da5a5a13f5d545b6045c6))
|
||||||
|
* scale up immediately when instance is lost ([43525d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43525d41a3884c00f1db26bf3c8c4cd9a607c260))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-14)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* scale up on high CPU load, not just subscription count ([255e2da](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/255e2da33c37e186ed14f2862f2d2e1b4adc59bf))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* don't block event loop during scale-down drain ([1d121c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1d121c727cbd4df477827cf64d065b7356a56e59))
|
||||||
|
* don't trigger scale-down if already at min replicas ([4b3b5e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4b3b5e7c4ed9b3cd4fe2490e9f268f2e3a0d9e85))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* force-delete hanging pods and remove failed instances from registry ([960a419](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/960a419792e1161fb7241e465b7349efe4a10137))
|
||||||
|
* linter formatting and improve code readability ([4a36096](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4a36096a5586e3f321d9c34c53e60d02bcc02c55))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* scalafix violations in metrics check and health monitor ([b991878](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b99187821489b296d66da5a5a13f5d545b6045c6))
|
||||||
|
* scale up immediately when instance is lost ([43525d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43525d41a3884c00f1db26bf3c8c4cd9a607c260))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* scale up on high CPU load, not just subscription count ([255e2da](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/255e2da33c37e186ed14f2862f2d2e1b4adc59bf))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* don't block event loop during scale-down drain ([1d121c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1d121c727cbd4df477827cf64d065b7356a56e59))
|
||||||
|
* don't trigger scale-down if already at min replicas ([4b3b5e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4b3b5e7c4ed9b3cd4fe2490e9f268f2e3a0d9e85))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* force-delete hanging pods and remove failed instances from registry ([960a419](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/960a419792e1161fb7241e465b7349efe4a10137))
|
||||||
|
* linter formatting and improve code readability ([4a36096](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4a36096a5586e3f321d9c34c53e60d02bcc02c55))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* scalafix violations in metrics check and health monitor ([b991878](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b99187821489b296d66da5a5a13f5d545b6045c6))
|
||||||
|
* scale up immediately when instance is lost ([43525d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43525d41a3884c00f1db26bf3c8c4cd9a607c260))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement clock expiry scanning and handling for game records ([#53](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/53)) ([8f9eb12](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8f9eb12f663efabe4dc72b94394438652ad0ef02))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* scale up on high CPU load, not just subscription count ([255e2da](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/255e2da33c37e186ed14f2862f2d2e1b4adc59bf))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* don't block event loop during scale-down drain ([1d121c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1d121c727cbd4df477827cf64d065b7356a56e59))
|
||||||
|
* don't trigger scale-down if already at min replicas ([4b3b5e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4b3b5e7c4ed9b3cd4fe2490e9f268f2e3a0d9e85))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* force-delete hanging pods and remove failed instances from registry ([960a419](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/960a419792e1161fb7241e465b7349efe4a10137))
|
||||||
|
* linter formatting and improve code readability ([4a36096](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4a36096a5586e3f321d9c34c53e60d02bcc02c55))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* scalafix violations in metrics check and health monitor ([b991878](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b99187821489b296d66da5a5a13f5d545b6045c6))
|
||||||
|
* scale up immediately when instance is lost ([43525d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43525d41a3884c00f1db26bf3c8c4cd9a607c260))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add coordinator startup validation and K8s pod watch ([81b045d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/81b045d01bb054a4bc9dc9e02fc30f814e756205))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* add periodic health check to evict dead instances ([380a2cc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/380a2cceeb5873bf93ff17a1e87d62408ef8e178))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement clock expiry scanning and handling for game records ([#53](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/53)) ([8f9eb12](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8f9eb12f663efabe4dc72b94394438652ad0ef02))
|
||||||
|
* implement clock expiry scanning and handling for game records ([#54](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/54)) ([2e4ba43](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2e4ba435978ef415b4ee2d7d2fc4af3b4e834b3d))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* scale up on high CPU load, not just subscription count ([255e2da](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/255e2da33c37e186ed14f2862f2d2e1b4adc59bf))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add instance-dead-timeout configuration and update HealthMonitor to use it for stale instance eviction ([be0b710](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/be0b710543b542da5c301efef7d2d587d0ba758a))
|
||||||
|
* clean up code formatting and improve error handling in gRPC server and failover service ([ad9495a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ad9495afa3e93593b57154a187346c9b01393911))
|
||||||
|
* coordinator auto-scaling, cache eviction, rebalancing, and grpc timeouts ([d0c7169](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d0c71693bb6f55fafdce5bcea0d5f38b9bb505ef))
|
||||||
|
* **coordinator:** refine type casting in rolloutSpec method ([#45](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/45)) ([d522f7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d522f7f6edf9c985f03dd16816439d4184f1a589))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#43](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/43)) ([fa3c6b2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fa3c6b2886dc59c14c5dad834acc9b41e42023bb))
|
||||||
|
* **coordinator:** use genericKubernetesResources API for Argo Rollout scaling ([#44](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/44)) ([82d0b75](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/82d0b754be1075084944b466858672d944f9f7d8))
|
||||||
|
* **dependencies:** replace Fabric8 Kubernetes client with Quarkus Kubernetes client ([5f44570](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5f44570b357277d09f33b7296860c421e2e70ce0))
|
||||||
|
* don't block event loop during scale-down drain ([1d121c7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1d121c727cbd4df477827cf64d065b7356a56e59))
|
||||||
|
* don't trigger scale-down if already at min replicas ([4b3b5e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4b3b5e7c4ed9b3cd4fe2490e9f268f2e3a0d9e85))
|
||||||
|
* enhance AutoScaler and InstanceRegistry for replica management and stale instance eviction ([b4920d3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b4920d3817e58bda94d7764e608b856ce9a909f7))
|
||||||
|
* force-delete hanging pods and remove failed instances from registry ([960a419](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/960a419792e1161fb7241e465b7349efe4a10137))
|
||||||
|
* linter formatting and improve code readability ([4a36096](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4a36096a5586e3f321d9c34c53e60d02bcc02c55))
|
||||||
|
* **middleware:** update paths for bot generation and stockfish configuration ([2dd0501](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2dd0501687db08dcd242359f6837125baf8a2fdc))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
||||||
|
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
||||||
|
* scalafix violations in metrics check and health monitor ([b991878](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b99187821489b296d66da5a5a13f5d545b6045c6))
|
||||||
|
* scale up immediately when instance is lost ([43525d4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43525d41a3884c00f1db26bf3c8c4cd9a607c260))
|
||||||
|
* streamline logging for evicted instances in InstanceRegistry ([10937e7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/10937e756a56e0e8fcf939decfdcaa4394506cc0))
|
||||||
|
* update grpcServer variable to use Instance wrapper and add optional access method ([d5c8da2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d5c8da20f8805199e920ea5afbd9cdb39a078e40))
|
||||||
|
* update HealthMonitor to evict instances without associated pods ([0f41f13](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0f41f13ce68b76846684bab67241a122250dfaf9))
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ dependencies {
|
|||||||
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
||||||
implementation("io.quarkus:quarkus-redis-client")
|
implementation("io.quarkus:quarkus-redis-client")
|
||||||
implementation("io.quarkus:quarkus-kubernetes-client")
|
implementation("io.quarkus:quarkus-kubernetes-client")
|
||||||
|
implementation("io.quarkus:quarkus-scheduler")
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:${versions["JUNIT_BOM"]!!}"))
|
testImplementation(platform("org.junit:junit-bom:${versions["JUNIT_BOM"]!!}"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ nowchess:
|
|||||||
internal:
|
internal:
|
||||||
secret: ${INTERNAL_SECRET:123abc}
|
secret: ${INTERNAL_SECRET:123abc}
|
||||||
coordinator:
|
coordinator:
|
||||||
max-games-per-core: 500
|
max-games-per-core: 100
|
||||||
max-deviation-percent: 20
|
max-deviation-percent: 20
|
||||||
rebalance-interval: 30s
|
rebalance-interval: 30s
|
||||||
rebalance-min-interval: 60s
|
rebalance-min-interval: 60s
|
||||||
@@ -37,7 +37,7 @@ nowchess:
|
|||||||
stream-heartbeat-interval: PT0.2S
|
stream-heartbeat-interval: PT0.2S
|
||||||
cache-eviction-interval: 10m
|
cache-eviction-interval: 10m
|
||||||
game-idle-threshold: 45m
|
game-idle-threshold: 45m
|
||||||
auto-scale-enabled: false
|
auto-scale-enabled: true
|
||||||
scale-up-threshold: 0.8
|
scale-up-threshold: 0.8
|
||||||
scale-down-threshold: 0.3
|
scale-down-threshold: 0.3
|
||||||
scale-min-replicas: 2
|
scale-min-replicas: 2
|
||||||
@@ -47,6 +47,8 @@ nowchess:
|
|||||||
k8s-rollout-label-selector: "app=nowchess-core"
|
k8s-rollout-label-selector: "app=nowchess-core"
|
||||||
startup-validation-timeout: 15s
|
startup-validation-timeout: 15s
|
||||||
failover-wait-timeout: 30s
|
failover-wait-timeout: 30s
|
||||||
|
scale-cpu-threshold-percent: 0.8
|
||||||
|
scale-memory-threshold-percent: 0.8
|
||||||
|
|
||||||
---
|
---
|
||||||
# dev profile
|
# dev profile
|
||||||
|
|||||||
+6
@@ -62,3 +62,9 @@ trait CoordinatorConfig:
|
|||||||
|
|
||||||
@WithName("failover-wait-timeout")
|
@WithName("failover-wait-timeout")
|
||||||
def failoverWaitTimeout: Duration
|
def failoverWaitTimeout: Duration
|
||||||
|
|
||||||
|
@WithName("scale-cpu-threshold-percent")
|
||||||
|
def scaleCpuThresholdPercent: Double
|
||||||
|
|
||||||
|
@WithName("scale-memory-threshold-percent")
|
||||||
|
def scaleMemoryThresholdPercent: Double
|
||||||
|
|||||||
+2
-1
@@ -127,7 +127,8 @@ class CoordinatorGrpcServer extends CoordinatorServiceGrpc.CoordinatorServiceImp
|
|||||||
_ =>
|
_ =>
|
||||||
val response = DrainInstanceResponse.newBuilder().setGamesMigrated(gamesBefore).build()
|
val response = DrainInstanceResponse.newBuilder().setGamesMigrated(gamesBefore).build()
|
||||||
responseObserver.onNext(response)
|
responseObserver.onNext(response)
|
||||||
responseObserver.onCompleted(),
|
responseObserver.onCompleted()
|
||||||
|
,
|
||||||
ex =>
|
ex =>
|
||||||
log.warnf(ex, "Drain failed for %s", instanceId)
|
log.warnf(ex, "Drain failed for %s", instanceId)
|
||||||
responseObserver.onError(ex),
|
responseObserver.onError(ex),
|
||||||
|
|||||||
+3
-3
@@ -39,7 +39,7 @@ class CoreGrpcClient:
|
|||||||
|
|
||||||
def batchResubscribeGames(host: String, port: Int, gameIds: List[String]): Int =
|
def batchResubscribeGames(host: String, port: Int, gameIds: List[String]): Int =
|
||||||
try
|
try
|
||||||
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
||||||
val request = BatchResubscribeRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
val request = BatchResubscribeRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
||||||
val count = stub.batchResubscribeGames(request).getSubscribedCount
|
val count = stub.batchResubscribeGames(request).getSubscribedCount
|
||||||
log.debugf("batchResubscribeGames %s:%d — subscribed %d games", host, port, count)
|
log.debugf("batchResubscribeGames %s:%d — subscribed %d games", host, port, count)
|
||||||
@@ -52,7 +52,7 @@ class CoreGrpcClient:
|
|||||||
|
|
||||||
def unsubscribeGames(host: String, port: Int, gameIds: List[String]): Int =
|
def unsubscribeGames(host: String, port: Int, gameIds: List[String]): Int =
|
||||||
try
|
try
|
||||||
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
||||||
val request = UnsubscribeGamesRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
val request = UnsubscribeGamesRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
||||||
val count = stub.unsubscribeGames(request).getUnsubscribedCount
|
val count = stub.unsubscribeGames(request).getUnsubscribedCount
|
||||||
log.debugf("unsubscribeGames %s:%d — unsubscribed %d games", host, port, count)
|
log.debugf("unsubscribeGames %s:%d — unsubscribed %d games", host, port, count)
|
||||||
@@ -65,7 +65,7 @@ class CoreGrpcClient:
|
|||||||
|
|
||||||
def evictGames(host: String, port: Int, gameIds: List[String]): Int =
|
def evictGames(host: String, port: Int, gameIds: List[String]): Int =
|
||||||
try
|
try
|
||||||
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
||||||
val request = EvictGamesRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
val request = EvictGamesRequest.newBuilder().addAllGameIds(gameIds.asJava).build()
|
||||||
val count = stub.evictGames(request).getEvictedCount
|
val count = stub.evictGames(request).getEvictedCount
|
||||||
log.debugf("evictGames %s:%d — evicted %d games", host, port, count)
|
log.debugf("evictGames %s:%d — evicted %d games", host, port, count)
|
||||||
|
|||||||
+232
-85
@@ -8,9 +8,13 @@ import de.nowchess.coordinator.config.CoordinatorConfig
|
|||||||
import io.fabric8.kubernetes.api.model.GenericKubernetesResource
|
import io.fabric8.kubernetes.api.model.GenericKubernetesResource
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient
|
import io.fabric8.kubernetes.client.KubernetesClient
|
||||||
import io.micrometer.core.instrument.{Gauge, MeterRegistry}
|
import io.micrometer.core.instrument.{Gauge, MeterRegistry}
|
||||||
|
import io.quarkus.scheduler.Scheduled
|
||||||
import org.jboss.logging.Logger
|
import org.jboss.logging.Logger
|
||||||
|
import io.fabric8.kubernetes.client.KubernetesClientException
|
||||||
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
@@ -25,20 +29,37 @@ class AutoScaler:
|
|||||||
@Inject
|
@Inject
|
||||||
private var instanceRegistry: InstanceRegistry = uninitialized
|
private var instanceRegistry: InstanceRegistry = uninitialized
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private var loadBalancer: LoadBalancer = uninitialized
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private var failoverService: FailoverService = uninitialized
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private var meterRegistry: MeterRegistry = uninitialized
|
private var meterRegistry: MeterRegistry = uninitialized
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[AutoScaler])
|
private val log = Logger.getLogger(classOf[AutoScaler])
|
||||||
private val lastScaleTime = new java.util.concurrent.atomic.AtomicLong(0L)
|
private val lastScaleTime = new java.util.concurrent.atomic.AtomicLong(0L)
|
||||||
private val avgLoadRef = new AtomicReference[Double](0.0)
|
private val avgLoadRef = new AtomicReference[Double](0.0)
|
||||||
|
private val drainingForScaleDown = ConcurrentHashMap.newKeySet[String]()
|
||||||
|
|
||||||
|
def isDrainingForScaleDown(instanceId: String): Boolean =
|
||||||
|
drainingForScaleDown.contains(instanceId)
|
||||||
|
|
||||||
|
def clearDraining(instanceId: String): Unit =
|
||||||
|
drainingForScaleDown.remove(instanceId)
|
||||||
|
|
||||||
|
def clearDrainingByPodName(podName: String): Unit =
|
||||||
|
drainingForScaleDown.asScala.find(podName.contains).foreach(drainingForScaleDown.remove)
|
||||||
|
|
||||||
private def kubeClientOpt: Option[KubernetesClient] =
|
private def kubeClientOpt: Option[KubernetesClient] =
|
||||||
if kubeClientInstance.isUnsatisfied then None
|
if kubeClientInstance.isUnsatisfied then None
|
||||||
else Some(kubeClientInstance.get())
|
else Some(kubeClientInstance.get())
|
||||||
|
|
||||||
private val argoApiVersion = "argoproj.io/v1alpha1"
|
private val argoApiVersion = "argoproj.io/v1alpha1"
|
||||||
private val argoKind = "Rollout"
|
private val argoKind = "Rollout"
|
||||||
|
private val metricsApiVersion = "metrics.k8s.io/v1beta1"
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
def initMetrics(): Unit =
|
def initMetrics(): Unit =
|
||||||
@@ -51,6 +72,11 @@ class AutoScaler:
|
|||||||
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", "down").increment(0)
|
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", "down").increment(0)
|
||||||
()
|
()
|
||||||
|
|
||||||
|
@Scheduled(every = "10s")
|
||||||
|
def periodicScaleCheck(): Unit =
|
||||||
|
try checkAndScale
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Auto-scale check failed")
|
||||||
|
|
||||||
// scalafix:off DisableSyntax.asInstanceOf
|
// scalafix:off DisableSyntax.asInstanceOf
|
||||||
private def rolloutSpec(rollout: GenericKubernetesResource): Option[java.util.Map[String, AnyRef]] =
|
private def rolloutSpec(rollout: GenericKubernetesResource): Option[java.util.Map[String, AnyRef]] =
|
||||||
Option(rollout.get[AnyRef]("spec")).collect { case m: java.util.Map[?, ?] =>
|
Option(rollout.get[AnyRef]("spec")).collect { case m: java.util.Map[?, ?] =>
|
||||||
@@ -58,6 +84,83 @@ class AutoScaler:
|
|||||||
}
|
}
|
||||||
// scalafix:on DisableSyntax.asInstanceOf
|
// scalafix:on DisableSyntax.asInstanceOf
|
||||||
|
|
||||||
|
private def parseMillicores(s: String): Long =
|
||||||
|
if s.endsWith("n") then s.dropRight(1).toLongOption.map(_ / 1000000).getOrElse(0L)
|
||||||
|
else if s.endsWith("m") then s.dropRight(1).toLongOption.getOrElse(0L)
|
||||||
|
else s.toLongOption.map(_ * 1000).getOrElse(0L)
|
||||||
|
|
||||||
|
private def parseBytes(s: String): Long =
|
||||||
|
if s.endsWith("Ki") then s.dropRight(2).toLongOption.map(_ * 1024L).getOrElse(0L)
|
||||||
|
else if s.endsWith("Mi") then s.dropRight(2).toLongOption.map(_ * 1024L * 1024L).getOrElse(0L)
|
||||||
|
else if s.endsWith("Gi") then s.dropRight(2).toLongOption.map(_ * 1024L * 1024L * 1024L).getOrElse(0L)
|
||||||
|
else if s.endsWith("K") then s.dropRight(1).toLongOption.map(_ * 1000L).getOrElse(0L)
|
||||||
|
else if s.endsWith("M") then s.dropRight(1).toLongOption.map(_ * 1000L * 1000L).getOrElse(0L)
|
||||||
|
else if s.endsWith("G") then s.dropRight(1).toLongOption.map(_ * 1000L * 1000L * 1000L).getOrElse(0L)
|
||||||
|
else s.toLongOption.getOrElse(0L)
|
||||||
|
|
||||||
|
private def exceedsRatio(used: Long, request: Long, threshold: Double, resource: String, instanceId: String): Boolean =
|
||||||
|
if request <= 0 then false
|
||||||
|
else
|
||||||
|
val ratio = used.toDouble / request.toDouble
|
||||||
|
log.debugf(
|
||||||
|
"Instance %s %s: %d used / %d requested = %.0f%%",
|
||||||
|
instanceId,
|
||||||
|
resource,
|
||||||
|
used,
|
||||||
|
request,
|
||||||
|
ratio * 100,
|
||||||
|
)
|
||||||
|
ratio > threshold
|
||||||
|
|
||||||
|
// scalafix:off DisableSyntax.asInstanceOf
|
||||||
|
private def isResourceConstrained(instanceId: String): Boolean =
|
||||||
|
kubeClientOpt.fold(false) { kube =>
|
||||||
|
try
|
||||||
|
val pods =
|
||||||
|
kube.pods().inNamespace(config.k8sNamespace).withLabel(config.k8sRolloutLabelSelector).list().getItems.asScala
|
||||||
|
pods.find(_.getMetadata.getName.contains(instanceId)).exists { pod =>
|
||||||
|
try
|
||||||
|
val requests = Option(pod.getSpec)
|
||||||
|
.flatMap(s => Option(s.getContainers))
|
||||||
|
.flatMap(cs => if cs.isEmpty then None else Option(cs.get(0)))
|
||||||
|
.flatMap(c => Option(c.getResources))
|
||||||
|
.flatMap(r => Option(r.getRequests))
|
||||||
|
|
||||||
|
val cpuRequestMillis = requests.flatMap(m => Option(m.get("cpu"))).map(q => parseMillicores(q.toString)).getOrElse(0L)
|
||||||
|
val memRequestBytes = requests.flatMap(m => Option(m.get("memory"))).map(q => parseBytes(q.toString)).getOrElse(0L)
|
||||||
|
|
||||||
|
if cpuRequestMillis <= 0 && memRequestBytes <= 0 then
|
||||||
|
log.debugf("No resource requests found for instance %s, skipping resource check", instanceId)
|
||||||
|
false
|
||||||
|
else
|
||||||
|
val metricsRes = kube
|
||||||
|
.genericKubernetesResources(metricsApiVersion, "PodMetrics")
|
||||||
|
.inNamespace(config.k8sNamespace)
|
||||||
|
.withName(pod.getMetadata.getName)
|
||||||
|
.get()
|
||||||
|
val metricsMap = metricsRes.asInstanceOf[java.util.Map[String, AnyRef]]
|
||||||
|
val usageOpt = Option(metricsMap.get("metrics"))
|
||||||
|
.map(_.asInstanceOf[java.util.Map[String, AnyRef]])
|
||||||
|
.flatMap(m => Option(m.get("containers")).map(_.asInstanceOf[java.util.List[AnyRef]]))
|
||||||
|
.filter(!_.isEmpty)
|
||||||
|
.map(_.get(0).asInstanceOf[java.util.Map[String, AnyRef]])
|
||||||
|
.flatMap(c => Option(c.get("usage")).map(_.asInstanceOf[java.util.Map[String, AnyRef]]))
|
||||||
|
|
||||||
|
usageOpt.exists { usage =>
|
||||||
|
val cpuUsed = Option(usage.get("cpu")).map(v => parseMillicores(v.toString)).getOrElse(0L)
|
||||||
|
val memUsed = Option(usage.get("memory")).map(v => parseBytes(v.toString)).getOrElse(0L)
|
||||||
|
exceedsRatio(cpuUsed, cpuRequestMillis, config.scaleCpuThresholdPercent, "CPU", instanceId) ||
|
||||||
|
exceedsRatio(memUsed, memRequestBytes, config.scaleMemoryThresholdPercent, "memory", instanceId)
|
||||||
|
}
|
||||||
|
catch case _: Exception => false
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
case ex: Exception =>
|
||||||
|
log.debugf(ex, "Failed to check resource metrics for %s", instanceId)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
// scalafix:on DisableSyntax.asInstanceOf
|
||||||
|
|
||||||
def checkAndScale: Unit =
|
def checkAndScale: Unit =
|
||||||
if config.autoScaleEnabled then
|
if config.autoScaleEnabled then
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
@@ -65,94 +168,138 @@ class AutoScaler:
|
|||||||
if now - last >= 120000 && lastScaleTime.compareAndSet(last, now) then
|
if now - last >= 120000 && lastScaleTime.compareAndSet(last, now) then
|
||||||
val instances = instanceRegistry.getAllInstances.filter(_.state == "HEALTHY")
|
val instances = instanceRegistry.getAllInstances.filter(_.state == "HEALTHY")
|
||||||
if instances.nonEmpty then
|
if instances.nonEmpty then
|
||||||
val avgLoad = instances.map(_.subscriptionCount).sum.toDouble / instances.size
|
val avgLoad = instances.map(_.subscriptionCount).sum.toDouble / instances.size
|
||||||
|
val scaleUpLoad = config.scaleUpThreshold * config.maxGamesPerCore
|
||||||
|
val scaleDownLoad = config.scaleDownThreshold * config.maxGamesPerCore
|
||||||
avgLoadRef.set(avgLoad)
|
avgLoadRef.set(avgLoad)
|
||||||
|
|
||||||
if avgLoad > config.scaleUpThreshold * config.maxGamesPerCore then scaleUp()
|
val constrainedInstance = instances.find(inst => isResourceConstrained(inst.instanceId))
|
||||||
else if avgLoad < config.scaleDownThreshold * config.maxGamesPerCore then scaleDown()
|
val hasHighCpuOrMemory = constrainedInstance.isDefined
|
||||||
|
|
||||||
|
log.infof(
|
||||||
|
"Scale check: instances=%d avgLoad=%.1f scaleUpAt=%.1f scaleDownAt=%.1f resourceConstrained=%s",
|
||||||
|
instances.size,
|
||||||
|
avgLoad,
|
||||||
|
scaleUpLoad,
|
||||||
|
scaleDownLoad,
|
||||||
|
constrainedInstance.map(_.instanceId).getOrElse("none"),
|
||||||
|
)
|
||||||
|
|
||||||
|
if avgLoad > scaleUpLoad || hasHighCpuOrMemory then scaleUp()
|
||||||
|
else if avgLoad < scaleDownLoad && instances.size > config.scaleMinReplicas
|
||||||
|
then scaleDown()
|
||||||
|
|
||||||
|
private def patchRolloutReplicas(
|
||||||
|
kube: KubernetesClient,
|
||||||
|
direction: String,
|
||||||
|
delta: Int,
|
||||||
|
canScale: Int => Boolean,
|
||||||
|
atLimit: Int => Unit,
|
||||||
|
onSuccess: (Int, Int) => Unit,
|
||||||
|
maxRetries: Int = 3,
|
||||||
|
): Unit =
|
||||||
|
def attempt(retries: Int): Unit =
|
||||||
|
try
|
||||||
|
Option(
|
||||||
|
kube
|
||||||
|
.genericKubernetesResources(argoApiVersion, argoKind)
|
||||||
|
.inNamespace(config.k8sNamespace)
|
||||||
|
.withName(config.k8sRolloutName)
|
||||||
|
.get(),
|
||||||
|
).foreach { rollout =>
|
||||||
|
rolloutSpec(rollout).foreach { spec =>
|
||||||
|
spec.get("replicas") match
|
||||||
|
case current: Integer =>
|
||||||
|
val n = current.intValue()
|
||||||
|
if !canScale(n) then atLimit(n)
|
||||||
|
else
|
||||||
|
spec.put("replicas", Integer.valueOf(n + delta))
|
||||||
|
kube
|
||||||
|
.genericKubernetesResources(argoApiVersion, argoKind)
|
||||||
|
.inNamespace(config.k8sNamespace)
|
||||||
|
.resource(rollout)
|
||||||
|
.update()
|
||||||
|
meterRegistry.counter("nowchess.coordinator.scale.events", "direction", direction).increment()
|
||||||
|
onSuccess(n, n + delta)
|
||||||
|
case _ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
case ex: KubernetesClientException if ex.getCode == 409 =>
|
||||||
|
if retries > 0 then
|
||||||
|
log.debugf("Conflict scaling %s %s, retrying (%d left)", direction, config.k8sRolloutName, retries - 1)
|
||||||
|
attempt(retries - 1)
|
||||||
|
else
|
||||||
|
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", direction).increment()
|
||||||
|
log.errorf(ex, "Failed to scale %s %s after conflict retries", direction, config.k8sRolloutName)
|
||||||
|
case ex: Exception =>
|
||||||
|
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", direction).increment()
|
||||||
|
log.errorf(ex, "Failed to scale %s %s", direction, config.k8sRolloutName)
|
||||||
|
attempt(maxRetries)
|
||||||
|
|
||||||
def scaleUp(): Unit =
|
def scaleUp(): Unit =
|
||||||
log.info("Scaling up Argo Rollout")
|
log.info("Scaling up Argo Rollout")
|
||||||
kubeClientOpt match
|
kubeClientOpt match
|
||||||
case None =>
|
case None => log.warn("Kubernetes client not available, cannot scale")
|
||||||
log.warn("Kubernetes client not available, cannot scale")
|
|
||||||
case Some(kube) =>
|
case Some(kube) =>
|
||||||
try
|
patchRolloutReplicas(
|
||||||
Option(
|
kube,
|
||||||
kube
|
direction = "up",
|
||||||
.genericKubernetesResources(argoApiVersion, argoKind)
|
delta = 1,
|
||||||
.inNamespace(config.k8sNamespace)
|
canScale = _ < config.scaleMaxReplicas,
|
||||||
.withName(config.k8sRolloutName)
|
atLimit = n => log.infof("Already at max replicas %d for %s", n, config.k8sRolloutName),
|
||||||
.get(),
|
onSuccess = (from, to) =>
|
||||||
).foreach { rollout =>
|
log.infof("Scaled up %s from %d to %d replicas", config.k8sRolloutName, from, to)
|
||||||
rolloutSpec(rollout).foreach { spec =>
|
loadBalancer.rebalance,
|
||||||
spec.get("replicas") match
|
)
|
||||||
case replicas: Integer =>
|
|
||||||
val currentReplicas = replicas.intValue()
|
|
||||||
val maxReplicas = config.scaleMaxReplicas
|
|
||||||
|
|
||||||
if currentReplicas < maxReplicas then
|
|
||||||
spec.put("replicas", Integer.valueOf(currentReplicas + 1))
|
|
||||||
kube
|
|
||||||
.genericKubernetesResources(argoApiVersion, argoKind)
|
|
||||||
.inNamespace(config.k8sNamespace)
|
|
||||||
.resource(rollout)
|
|
||||||
.update()
|
|
||||||
meterRegistry.counter("nowchess.coordinator.scale.events", "direction", "up").increment()
|
|
||||||
log.infof(
|
|
||||||
"Scaled up %s from %d to %d replicas",
|
|
||||||
config.k8sRolloutName,
|
|
||||||
currentReplicas,
|
|
||||||
currentReplicas + 1,
|
|
||||||
)
|
|
||||||
else log.infof("Already at max replicas %d for %s", maxReplicas, config.k8sRolloutName)
|
|
||||||
case _ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
case ex: Exception =>
|
|
||||||
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", "up").increment()
|
|
||||||
log.warnf(ex, "Failed to scale up %s", config.k8sRolloutName)
|
|
||||||
|
|
||||||
def scaleDown(): Unit =
|
def scaleDown(): Unit =
|
||||||
log.info("Scaling down Argo Rollout")
|
log.info("Scaling down Argo Rollout")
|
||||||
kubeClientOpt match
|
val underloadedInstance = instanceRegistry.getAllInstances
|
||||||
case None =>
|
.filter(_.state == "HEALTHY")
|
||||||
log.warn("Kubernetes client not available, cannot scale")
|
.minByOption(_.subscriptionCount)
|
||||||
case Some(kube) =>
|
|
||||||
try
|
|
||||||
Option(
|
|
||||||
kube
|
|
||||||
.genericKubernetesResources(argoApiVersion, argoKind)
|
|
||||||
.inNamespace(config.k8sNamespace)
|
|
||||||
.withName(config.k8sRolloutName)
|
|
||||||
.get(),
|
|
||||||
).foreach { rollout =>
|
|
||||||
rolloutSpec(rollout).foreach { spec =>
|
|
||||||
spec.get("replicas") match
|
|
||||||
case replicas: Integer =>
|
|
||||||
val currentReplicas = replicas.intValue()
|
|
||||||
val minReplicas = config.scaleMinReplicas
|
|
||||||
|
|
||||||
if currentReplicas > minReplicas then
|
underloadedInstance.foreach { inst =>
|
||||||
spec.put("replicas", Integer.valueOf(currentReplicas - 1))
|
log.infof("Marking instance %s for drain before scale-down", inst.instanceId)
|
||||||
kube
|
drainingForScaleDown.add(inst.instanceId)
|
||||||
.genericKubernetesResources(argoApiVersion, argoKind)
|
failoverService
|
||||||
.inNamespace(config.k8sNamespace)
|
.onInstanceStreamDropped(inst.instanceId)
|
||||||
.resource(rollout)
|
.subscribe()
|
||||||
.update()
|
.`with`(
|
||||||
meterRegistry.counter("nowchess.coordinator.scale.events", "direction", "down").increment()
|
_ => log.debugf("Instance %s drained for scale-down", inst.instanceId),
|
||||||
log.infof(
|
ex => log.warnf(ex, "Drain failed for %s, proceeding with scale-down", inst.instanceId),
|
||||||
"Scaled down %s from %d to %d replicas",
|
)
|
||||||
config.k8sRolloutName,
|
}
|
||||||
currentReplicas,
|
|
||||||
currentReplicas - 1,
|
kubeClientOpt match
|
||||||
)
|
case None => log.warn("Kubernetes client not available, cannot scale")
|
||||||
else log.infof("Already at min replicas %d for %s", minReplicas, config.k8sRolloutName)
|
case Some(kube) =>
|
||||||
case _ => ()
|
patchRolloutReplicas(
|
||||||
}
|
kube,
|
||||||
}
|
direction = "down",
|
||||||
catch
|
delta = -1,
|
||||||
case ex: Exception =>
|
canScale = _ > config.scaleMinReplicas,
|
||||||
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", "down").increment()
|
atLimit = n => log.infof("Already at min replicas %d for %s", n, config.k8sRolloutName),
|
||||||
log.warnf(ex, "Failed to scale down %s", config.k8sRolloutName)
|
onSuccess = (from, to) =>
|
||||||
|
log.infof("Scaled down %s from %d to %d replicas", config.k8sRolloutName, from, to)
|
||||||
|
underloadedInstance.foreach(inst => forceDeletePod(inst.instanceId, kube)),
|
||||||
|
)
|
||||||
|
|
||||||
|
private def forceDeletePod(instanceId: String, kube: KubernetesClient): Unit =
|
||||||
|
try
|
||||||
|
val pods = kube
|
||||||
|
.pods()
|
||||||
|
.inNamespace(config.k8sNamespace)
|
||||||
|
.withLabel(config.k8sRolloutLabelSelector)
|
||||||
|
.list()
|
||||||
|
.getItems
|
||||||
|
.asScala
|
||||||
|
pods.find(_.getMetadata.getName.contains(instanceId)) match
|
||||||
|
case Some(pod) =>
|
||||||
|
kube.pods().inNamespace(config.k8sNamespace).withName(pod.getMetadata.getName).withGracePeriod(0L).delete()
|
||||||
|
log.infof("Force-deleted pod for drained instance %s", instanceId)
|
||||||
|
case None =>
|
||||||
|
log.debugf("No pod found for drained instance %s, skipping deletion", instanceId)
|
||||||
|
catch
|
||||||
|
case ex: Exception =>
|
||||||
|
log.warnf(ex, "Failed to force-delete pod for drained instance %s", instanceId)
|
||||||
|
|||||||
+8
-2
@@ -7,6 +7,7 @@ import io.quarkus.redis.datasource.RedisDataSource
|
|||||||
import de.nowchess.coordinator.config.CoordinatorConfig
|
import de.nowchess.coordinator.config.CoordinatorConfig
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import io.micrometer.core.instrument.MeterRegistry
|
import io.micrometer.core.instrument.MeterRegistry
|
||||||
|
import io.quarkus.scheduler.Scheduled
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
import org.jboss.logging.Logger
|
import org.jboss.logging.Logger
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
@@ -48,6 +49,11 @@ class CacheEvictionManager:
|
|||||||
meterRegistry.timer("nowchess.coordinator.cache.eviction.duration").record(0L, TimeUnit.MILLISECONDS)
|
meterRegistry.timer("nowchess.coordinator.cache.eviction.duration").record(0L, TimeUnit.MILLISECONDS)
|
||||||
meterRegistry.counter("nowchess.coordinator.cache.evictions").increment(0)
|
meterRegistry.counter("nowchess.coordinator.cache.evictions").increment(0)
|
||||||
|
|
||||||
|
@Scheduled(every = "5m")
|
||||||
|
def periodicCacheEviction(): Unit =
|
||||||
|
try evictStaleGames
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Periodic cache eviction failed")
|
||||||
|
|
||||||
def evictStaleGames: Unit =
|
def evictStaleGames: Unit =
|
||||||
meterRegistry.timer("nowchess.coordinator.cache.eviction.duration").record((() => runEviction()): Runnable)
|
meterRegistry.timer("nowchess.coordinator.cache.eviction.duration").record((() => runEviction()): Runnable)
|
||||||
|
|
||||||
@@ -74,14 +80,14 @@ class CacheEvictionManager:
|
|||||||
count + 1
|
count + 1
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to evict game %s", gameId)
|
log.errorf(ex, "Failed to evict game %s", gameId)
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
else count
|
else count
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Error processing game key %s", key)
|
log.errorf(ex, "Error processing game key %s", key)
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -112,7 +112,7 @@ class FailoverService:
|
|||||||
else false
|
else false
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to migrate batch to %s, trying next", target.instanceId)
|
log.errorf(ex, "Failed to migrate batch to %s, trying next", target.instanceId)
|
||||||
false
|
false
|
||||||
if success then true else tryMigrateBatch(batch, batchIdx, instances, deadId, attempt + 1)
|
if success then true else tryMigrateBatch(batch, batchIdx, instances, deadId, attempt + 1)
|
||||||
|
|
||||||
@@ -122,14 +122,17 @@ class FailoverService:
|
|||||||
log.infof("Cleaned up games set for instance %s", instanceId)
|
log.infof("Cleaned up games set for instance %s", instanceId)
|
||||||
|
|
||||||
private def waitForHealthyInstanceAsync(): Uni[InstanceMetadata] =
|
private def waitForHealthyInstanceAsync(): Uni[InstanceMetadata] =
|
||||||
Uni.createFrom().deferred(() =>
|
Uni
|
||||||
instanceRegistry.getAllInstances
|
.createFrom()
|
||||||
.filter(_.state == "HEALTHY")
|
.deferred(() =>
|
||||||
.sortBy(_.subscriptionCount)
|
instanceRegistry.getAllInstances
|
||||||
.headOption match
|
.filter(_.state == "HEALTHY")
|
||||||
|
.sortBy(_.subscriptionCount)
|
||||||
|
.headOption match
|
||||||
case Some(inst) => Uni.createFrom().item(inst)
|
case Some(inst) => Uni.createFrom().item(inst)
|
||||||
case None => Uni.createFrom().failure(new RuntimeException("no healthy instance"))
|
case None => Uni.createFrom().failure(new RuntimeException("no healthy instance")),
|
||||||
).onFailure()
|
)
|
||||||
|
.onFailure()
|
||||||
.retry()
|
.retry()
|
||||||
.withBackOff(Duration.ofMillis(500))
|
.withBackOff(Duration.ofMillis(500))
|
||||||
.expireIn(config.failoverWaitTimeout.toMillis)
|
.expireIn(config.failoverWaitTimeout.toMillis)
|
||||||
|
|||||||
+50
-27
@@ -5,6 +5,7 @@ import jakarta.enterprise.context.ApplicationScoped
|
|||||||
import jakarta.enterprise.event.Observes
|
import jakarta.enterprise.event.Observes
|
||||||
import jakarta.enterprise.inject.Instance
|
import jakarta.enterprise.inject.Instance
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
|
import io.quarkus.scheduler.Scheduled
|
||||||
import de.nowchess.coordinator.config.CoordinatorConfig
|
import de.nowchess.coordinator.config.CoordinatorConfig
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient
|
import io.fabric8.kubernetes.client.KubernetesClient
|
||||||
import io.fabric8.kubernetes.api.model.Pod
|
import io.fabric8.kubernetes.api.model.Pod
|
||||||
@@ -39,11 +40,14 @@ class HealthMonitor:
|
|||||||
private var meterRegistry: MeterRegistry = uninitialized
|
private var meterRegistry: MeterRegistry = uninitialized
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private var grpcServer: CoordinatorGrpcServer = uninitialized
|
private var grpcServerInstance: Instance[CoordinatorGrpcServer] = uninitialized
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private var failoverService: FailoverService = uninitialized
|
private var failoverService: FailoverService = uninitialized
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private var autoScaler: AutoScaler = uninitialized
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[HealthMonitor])
|
private val log = Logger.getLogger(classOf[HealthMonitor])
|
||||||
private var redisPrefix = "nowchess"
|
private var redisPrefix = "nowchess"
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
@@ -52,6 +56,10 @@ class HealthMonitor:
|
|||||||
if kubeClientInstance.isUnsatisfied then None
|
if kubeClientInstance.isUnsatisfied then None
|
||||||
else Some(kubeClientInstance.get())
|
else Some(kubeClientInstance.get())
|
||||||
|
|
||||||
|
private def grpcServerOpt: Option[CoordinatorGrpcServer] =
|
||||||
|
if grpcServerInstance.isUnsatisfied then None
|
||||||
|
else Some(grpcServerInstance.get())
|
||||||
|
|
||||||
def setRedisPrefix(prefix: String): Unit =
|
def setRedisPrefix(prefix: String): Unit =
|
||||||
redisPrefix = prefix
|
redisPrefix = prefix
|
||||||
|
|
||||||
@@ -69,20 +77,31 @@ class HealthMonitor:
|
|||||||
Thread.ofVirtual().start(() => validateStartupInstances(timeoutMs))
|
Thread.ofVirtual().start(() => validateStartupInstances(timeoutMs))
|
||||||
startPodWatch()
|
startPodWatch()
|
||||||
|
|
||||||
def checkInstanceHealth: Unit =
|
@Scheduled(every = "10s")
|
||||||
|
def periodicHealthCheck(): Unit =
|
||||||
|
try checkInstanceHealth()
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Health check failed")
|
||||||
|
|
||||||
|
def checkInstanceHealth(): Unit =
|
||||||
meterRegistry.counter("nowchess.coordinator.health.checks").increment()
|
meterRegistry.counter("nowchess.coordinator.health.checks").increment()
|
||||||
val evicted = instanceRegistry.evictStaleInstances(config.instanceDeadTimeout)
|
val evicted = instanceRegistry.evictStaleInstances(config.instanceDeadTimeout)
|
||||||
if evicted.nonEmpty then
|
if evicted.nonEmpty then
|
||||||
log.warnf("Evicted %d stale instances: %s", evicted.size, evicted.mkString(", "))
|
log.warnf("Evicted %d stale instances: %s", evicted.size, evicted.mkString(", "))
|
||||||
evicted.foreach(deleteK8sPod)
|
evicted.foreach(deleteK8sPod)
|
||||||
|
val unexpectedEvictions = evicted.filterNot(autoScaler.isDrainingForScaleDown)
|
||||||
|
if unexpectedEvictions.nonEmpty then autoScaler.scaleUp()
|
||||||
val instances = instanceRegistry.getAllInstances
|
val instances = instanceRegistry.getAllInstances
|
||||||
instances.foreach { inst =>
|
val failed = instances.collect { inst =>
|
||||||
val isHealthy = checkHealth(inst.instanceId)
|
val isHealthy = checkHealth(inst.instanceId)
|
||||||
if !isHealthy && inst.state == "HEALTHY" then
|
if !isHealthy && inst.state == "HEALTHY" then
|
||||||
log.warnf("Instance %s marked unhealthy", inst.instanceId)
|
log.warnf("Instance %s marked unhealthy", inst.instanceId)
|
||||||
instanceRegistry.markInstanceDead(inst.instanceId)
|
instanceRegistry.markInstanceDead(inst.instanceId)
|
||||||
deleteK8sPod(inst.instanceId)
|
deleteK8sPod(inst.instanceId)
|
||||||
}
|
Some(inst.instanceId)
|
||||||
|
else None
|
||||||
|
}.flatten
|
||||||
|
val unexpectedFailures = failed.filterNot(autoScaler.isDrainingForScaleDown)
|
||||||
|
if unexpectedFailures.nonEmpty then autoScaler.scaleUp()
|
||||||
|
|
||||||
private def checkHealth(instanceId: String): Boolean =
|
private def checkHealth(instanceId: String): Boolean =
|
||||||
val redisHealthy = checkRedisHeartbeat(instanceId)
|
val redisHealthy = checkRedisHeartbeat(instanceId)
|
||||||
@@ -133,19 +152,18 @@ class HealthMonitor:
|
|||||||
action match
|
action match
|
||||||
case Watcher.Action.DELETED =>
|
case Watcher.Action.DELETED =>
|
||||||
handlePodGone(pod)
|
handlePodGone(pod)
|
||||||
case Watcher.Action.MODIFIED
|
case Watcher.Action.MODIFIED if Option(pod.getMetadata.getDeletionTimestamp).isDefined =>
|
||||||
if Option(pod.getMetadata.getDeletionTimestamp).isDefined =>
|
|
||||||
handlePodTerminating(pod)
|
handlePodTerminating(pod)
|
||||||
case _ => ()
|
case _ => ()
|
||||||
|
|
||||||
override def onClose(cause: WatcherException): Unit =
|
override def onClose(cause: WatcherException): Unit =
|
||||||
if cause != null then
|
Option(cause).foreach { ex =>
|
||||||
log.warnf(cause, "Pod watch closed, restarting")
|
log.warnf(ex, "Pod watch closed, restarting")
|
||||||
startPodWatch()
|
startPodWatch()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
log.info("Pod watch started")
|
log.info("Pod watch started")
|
||||||
catch
|
catch case ex: Exception => log.warnf(ex, "Failed to start pod watch")
|
||||||
case ex: Exception => log.warnf(ex, "Failed to start pod watch")
|
|
||||||
|
|
||||||
private def isPodReady(pod: Pod): Boolean =
|
private def isPodReady(pod: Pod): Boolean =
|
||||||
Option(pod.getStatus)
|
Option(pod.getStatus)
|
||||||
@@ -169,26 +187,33 @@ class HealthMonitor:
|
|||||||
pods.find(pod => pod.getMetadata.getName.contains(instanceId)) match
|
pods.find(pod => pod.getMetadata.getName.contains(instanceId)) match
|
||||||
case Some(pod) =>
|
case Some(pod) =>
|
||||||
val podName = pod.getMetadata.getName
|
val podName = pod.getMetadata.getName
|
||||||
kube.pods().inNamespace(config.k8sNamespace).withName(podName).delete()
|
kube.pods().inNamespace(config.k8sNamespace).withName(podName).withGracePeriod(0L).delete()
|
||||||
meterRegistry.counter("nowchess.coordinator.pods.deleted").increment()
|
meterRegistry.counter("nowchess.coordinator.pods.deleted").increment()
|
||||||
log.infof("Deleted pod %s for dead instance %s", podName, instanceId)
|
log.infof("Force-deleted pod %s for dead instance %s", podName, instanceId)
|
||||||
case None =>
|
case None =>
|
||||||
log.debugf("No pod found for instance %s, skipping deletion", instanceId)
|
log.debugf("No pod found for instance %s, skipping deletion", instanceId)
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to delete pod for instance %s", instanceId)
|
log.errorf(
|
||||||
|
ex,
|
||||||
|
"Failed to delete pod for instance %s — removing from registry to prevent blocking scale-down",
|
||||||
|
instanceId,
|
||||||
|
)
|
||||||
|
instanceRegistry.removeInstance(instanceId)
|
||||||
|
|
||||||
private def validateStartupInstances(timeoutMs: Long): Unit =
|
private def validateStartupInstances(timeoutMs: Long): Unit =
|
||||||
Thread.sleep(timeoutMs)
|
Thread.sleep(timeoutMs)
|
||||||
instanceRegistry.getAllInstances.foreach { inst =>
|
grpcServerOpt.foreach { grpcServer =>
|
||||||
if !grpcServer.hasActiveStream(inst.instanceId) then
|
instanceRegistry.getAllInstances.foreach { inst =>
|
||||||
log.warnf(
|
if !grpcServer.hasActiveStream(inst.instanceId) then
|
||||||
"Startup: instance %s did not reconnect within %dms — evicting",
|
log.warnf(
|
||||||
inst.instanceId,
|
"Startup: instance %s did not reconnect within %dms — evicting",
|
||||||
timeoutMs,
|
inst.instanceId,
|
||||||
)
|
timeoutMs,
|
||||||
instanceRegistry.removeInstance(inst.instanceId)
|
)
|
||||||
deleteK8sPod(inst.instanceId)
|
instanceRegistry.removeInstance(inst.instanceId)
|
||||||
|
deleteK8sPod(inst.instanceId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def handlePodTerminating(pod: Pod): Unit =
|
private def handlePodTerminating(pod: Pod): Unit =
|
||||||
@@ -204,12 +229,10 @@ class HealthMonitor:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def handlePodGone(pod: Pod): Unit =
|
private def handlePodGone(pod: Pod): Unit =
|
||||||
|
val podName = pod.getMetadata.getName
|
||||||
|
autoScaler.clearDrainingByPodName(podName)
|
||||||
findRegisteredInstance(pod).foreach { inst =>
|
findRegisteredInstance(pod).foreach { inst =>
|
||||||
log.warnf(
|
log.warnf("Pod %s deleted — triggering failover for %s", podName, inst.instanceId)
|
||||||
"Pod %s deleted — triggering failover for %s",
|
|
||||||
pod.getMetadata.getName,
|
|
||||||
inst.instanceId,
|
|
||||||
)
|
|
||||||
failoverService
|
failoverService
|
||||||
.onInstanceStreamDropped(inst.instanceId)
|
.onInstanceStreamDropped(inst.instanceId)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|||||||
+35
-21
@@ -51,14 +51,15 @@ class InstanceRegistry:
|
|||||||
keys.asScala.foreach { key =>
|
keys.asScala.foreach { key =>
|
||||||
val instanceId = key.stripPrefix(s"$redisPrefix:instances:")
|
val instanceId = key.stripPrefix(s"$redisPrefix:instances:")
|
||||||
val json = syncRedis.value(classOf[String]).get(key)
|
val json = syncRedis.value(classOf[String]).get(key)
|
||||||
if json != null then
|
Option(json).foreach { jsonStr =>
|
||||||
try
|
try
|
||||||
val metadata = mapper.readValue(json, classOf[InstanceMetadata])
|
val metadata = mapper.readValue(jsonStr, classOf[InstanceMetadata])
|
||||||
instances.put(instanceId, metadata)
|
instances.put(instanceId, metadata)
|
||||||
log.infof("Startup: loaded instance %s from Redis", instanceId)
|
log.infof("Startup: loaded instance %s from Redis", instanceId)
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Startup: failed to parse instance %s", instanceId)
|
log.warnf(ex, "Startup: failed to parse instance %s", instanceId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def getInstance(instanceId: String): Option[InstanceMetadata] =
|
def getInstance(instanceId: String): Option[InstanceMetadata] =
|
||||||
@@ -75,23 +76,32 @@ class InstanceRegistry:
|
|||||||
.onItem()
|
.onItem()
|
||||||
.transformToUni { value =>
|
.transformToUni { value =>
|
||||||
try
|
try
|
||||||
val metadata = mapper.readValue(value, classOf[InstanceMetadata])
|
Option(value).fold(
|
||||||
val isNew = !instances.containsKey(instanceId)
|
{
|
||||||
instances.put(instanceId, metadata)
|
log.debugf("Instance %s metadata missing from Redis (may have expired)", instanceId)
|
||||||
if isNew then
|
Uni.createFrom().item(())
|
||||||
meterRegistry.counter("nowchess.coordinator.instances.joined").increment()
|
},
|
||||||
log.infof("Instance %s joined registry (subscriptions=%d)", instanceId, metadata.subscriptionCount)
|
) { json =>
|
||||||
else
|
val metadata = mapper.readValue(json, classOf[InstanceMetadata])
|
||||||
log.debugf(
|
val isNew = !instances.containsKey(instanceId)
|
||||||
"Instance %s updated (subscriptions=%d state=%s)",
|
instances.put(instanceId, metadata)
|
||||||
instanceId,
|
if isNew then
|
||||||
metadata.subscriptionCount,
|
meterRegistry.counter("nowchess.coordinator.instances.joined").increment()
|
||||||
metadata.state,
|
log.infof("Instance %s joined registry (subscriptions=%d)", instanceId, metadata.subscriptionCount)
|
||||||
)
|
else
|
||||||
Uni.createFrom().item(())
|
log.debugf(
|
||||||
|
"Instance %s updated (subscriptions=%d state=%s)",
|
||||||
|
instanceId,
|
||||||
|
metadata.subscriptionCount,
|
||||||
|
metadata.state,
|
||||||
|
)
|
||||||
|
Uni.createFrom().item(())
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to parse instance metadata for %s", instanceId)
|
log.errorf(ex, "Failed to parse instance metadata for %s — removing from registry", instanceId)
|
||||||
|
instances.remove(instanceId)
|
||||||
|
meterRegistry.counter("nowchess.coordinator.instances.removed").increment()
|
||||||
Uni.createFrom().item(())
|
Uni.createFrom().item(())
|
||||||
}
|
}
|
||||||
.onFailure()
|
.onFailure()
|
||||||
@@ -111,15 +121,19 @@ class InstanceRegistry:
|
|||||||
val stale = instances.asScala
|
val stale = instances.asScala
|
||||||
.collect { case (id, inst) =>
|
.collect { case (id, inst) =>
|
||||||
try
|
try
|
||||||
if Instant.parse(inst.lastHeartbeat).isBefore(cutoff) then Some(id)
|
val isHeartbeatStale = Instant.parse(inst.lastHeartbeat).isBefore(cutoff)
|
||||||
else None
|
val isDead = inst.state == "DEAD"
|
||||||
|
if isHeartbeatStale || isDead then Some(id) else None
|
||||||
catch case _: Exception => None
|
catch case _: Exception => None
|
||||||
}
|
}
|
||||||
.flatten
|
.flatten
|
||||||
.toList
|
.toList
|
||||||
stale.foreach { id =>
|
stale.foreach { id =>
|
||||||
instances.remove(id)
|
val inst = Option(instances.remove(id))
|
||||||
meterRegistry.counter("nowchess.coordinator.instances.evicted").increment()
|
meterRegistry.counter("nowchess.coordinator.instances.evicted").increment()
|
||||||
log.warnf("Evicted stale instance %s (heartbeat older than %s)", id, maxAge)
|
inst.foreach { i =>
|
||||||
|
if i.state == "DEAD" then log.warnf("Evicted dead instance %s", id)
|
||||||
|
else log.warnf("Evicted stale instance %s (heartbeat older than %s)", id, maxAge)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stale
|
stale
|
||||||
|
|||||||
+9
-3
@@ -4,6 +4,7 @@ import jakarta.enterprise.context.ApplicationScoped
|
|||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
import de.nowchess.coordinator.config.CoordinatorConfig
|
import de.nowchess.coordinator.config.CoordinatorConfig
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
|
import io.quarkus.scheduler.Scheduled
|
||||||
import org.jboss.logging.Logger
|
import org.jboss.logging.Logger
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import scala.concurrent.duration.*
|
import scala.concurrent.duration.*
|
||||||
@@ -95,14 +96,14 @@ class LoadBalancer:
|
|||||||
log.infof("Moved %d games from %s to %s", subscribed, over.instanceId, target.instanceId)
|
log.infof("Moved %d games from %s to %s", subscribed, over.instanceId, target.instanceId)
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to move games from %s to %s", over.instanceId, target.instanceId)
|
log.errorf(ex, "Failed to move games from %s to %s", over.instanceId, target.instanceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val elapsed = System.currentTimeMillis() - startTime
|
val elapsed = System.currentTimeMillis() - startTime
|
||||||
log.infof("Rebalance completed in %dms", elapsed)
|
log.infof("Rebalance completed in %dms", elapsed)
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Rebalance failed")
|
log.errorf(ex, "Rebalance failed")
|
||||||
|
|
||||||
private def getGamesToMove(instanceId: String, count: Int): List[String] =
|
private def getGamesToMove(instanceId: String, count: Int): List[String] =
|
||||||
try
|
try
|
||||||
@@ -124,4 +125,9 @@ class LoadBalancer:
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "Failed to update Redis game sets")
|
log.errorf(ex, "Failed to update Redis game sets")
|
||||||
|
|
||||||
|
@Scheduled(every = "30s")
|
||||||
|
def periodicRebalanceCheck(): Unit =
|
||||||
|
try if shouldRebalance then rebalance
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Periodic rebalance check failed")
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=18
|
MINOR=26
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -1195,3 +1195,305 @@
|
|||||||
|
|
||||||
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add CORS configuration and reorder JWT settings in application.yml ([a49f9be](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a49f9be146f04c14561c305d980846a92f8c12b2))
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-37 Quarkus integration ([#35](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/35)) ([f088c4e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f088c4e9ffcc498d3d1b6f01e8f50042d5830d55))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([33e785d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e785d22af87724839b62ae91dfe74a05b398c3))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
||||||
|
* NCS-53 changed IO to MicroService for easier scaling ([#37](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/37)) ([b5a2966](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b5a2966adafa9650f0f7d601bdeb8fdd13710327))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#48](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/48)) ([c96a09b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c96a09bb5cee59fc23205bb63baa8b217a7e1b00))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* **rule:** Rules as a microservice ([#39](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/39)) ([093134d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/093134d36c6844ba02a36a28d5d044f09291cd1d))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* **auth:** change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation ([c08d530](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c08d5303eb9e70d36c8eebf6a061ccb71e118fe5))
|
||||||
|
* **auth:** update InternalAuthFilter to use @ApplicationScoped and add index-dependency configuration ([6e0fd95](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e0fd9523e001756ce7109e639ebb54be4fcdabf))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* **heartbeat:** inject ObjectMapper into InstanceHeartbeatService ([#42](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/42)) ([0c98151](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0c981517da1f94cd10ae396e47bde2b35d0b3ba0))
|
||||||
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
* Lints ([dc224ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dc224abe26acf5361c56956006e1cc51b75b0b7e))
|
||||||
|
* **redis:** add max pool wait time and switch to ReactiveRedisDataSource for heartbeat updates ([33e5017](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e5017f51a998327b180f778f73964cc10c05d3))
|
||||||
|
* **redis:** enhance GameRedisSubscriberManager to use ReactiveRedisDataSource and improve subscription handling ([0eb752d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0eb752d4935377f75aab710b7f4eda4b29098e6a))
|
||||||
|
* **redis:** prevent concurrent Redis heartbeat refreshes using AtomicBoolean ([847b132](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/847b13202cb909d18ca3304c27ebe17ce2312b8e))
|
||||||
|
* **redis:** simplify refreshRedisHeartbeat logic and ensure proper error handling ([1813ea1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1813ea1d2d5d093f7925f87371b5e29820bf1136))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add CORS configuration and reorder JWT settings in application.yml ([a49f9be](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a49f9be146f04c14561c305d980846a92f8c12b2))
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-37 Quarkus integration ([#35](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/35)) ([f088c4e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f088c4e9ffcc498d3d1b6f01e8f50042d5830d55))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([33e785d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e785d22af87724839b62ae91dfe74a05b398c3))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
||||||
|
* NCS-53 changed IO to MicroService for easier scaling ([#37](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/37)) ([b5a2966](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b5a2966adafa9650f0f7d601bdeb8fdd13710327))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#48](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/48)) ([c96a09b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c96a09bb5cee59fc23205bb63baa8b217a7e1b00))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* **rule:** Rules as a microservice ([#39](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/39)) ([093134d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/093134d36c6844ba02a36a28d5d044f09291cd1d))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* **auth:** change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation ([c08d530](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c08d5303eb9e70d36c8eebf6a061ccb71e118fe5))
|
||||||
|
* **auth:** update InternalAuthFilter to use @ApplicationScoped and add index-dependency configuration ([6e0fd95](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e0fd9523e001756ce7109e639ebb54be4fcdabf))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* **heartbeat:** inject ObjectMapper into InstanceHeartbeatService ([#42](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/42)) ([0c98151](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0c981517da1f94cd10ae396e47bde2b35d0b3ba0))
|
||||||
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
* Lints ([dc224ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dc224abe26acf5361c56956006e1cc51b75b0b7e))
|
||||||
|
* **redis:** add max pool wait time and switch to ReactiveRedisDataSource for heartbeat updates ([33e5017](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e5017f51a998327b180f778f73964cc10c05d3))
|
||||||
|
* **redis:** enhance GameRedisSubscriberManager to use ReactiveRedisDataSource and improve subscription handling ([0eb752d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0eb752d4935377f75aab710b7f4eda4b29098e6a))
|
||||||
|
* **redis:** prevent concurrent Redis heartbeat refreshes using AtomicBoolean ([847b132](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/847b13202cb909d18ca3304c27ebe17ce2312b8e))
|
||||||
|
* **redis:** simplify refreshRedisHeartbeat logic and ensure proper error handling ([1813ea1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1813ea1d2d5d093f7925f87371b5e29820bf1136))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
* update documentation to reflect new functions in CoordinatorGrpcServer and InstanceRegistry ([f7ce4df](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f7ce4df595cbdc2ef84122781f4851ff140c0f44))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add CORS configuration and reorder JWT settings in application.yml ([a49f9be](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a49f9be146f04c14561c305d980846a92f8c12b2))
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-37 Quarkus integration ([#35](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/35)) ([f088c4e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f088c4e9ffcc498d3d1b6f01e8f50042d5830d55))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([33e785d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e785d22af87724839b62ae91dfe74a05b398c3))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
||||||
|
* NCS-53 changed IO to MicroService for easier scaling ([#37](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/37)) ([b5a2966](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b5a2966adafa9650f0f7d601bdeb8fdd13710327))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#48](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/48)) ([c96a09b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c96a09bb5cee59fc23205bb63baa8b217a7e1b00))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* **rule:** Rules as a microservice ([#39](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/39)) ([093134d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/093134d36c6844ba02a36a28d5d044f09291cd1d))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* **auth:** change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation ([c08d530](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c08d5303eb9e70d36c8eebf6a061ccb71e118fe5))
|
||||||
|
* **auth:** update InternalAuthFilter to use @ApplicationScoped and add index-dependency configuration ([6e0fd95](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e0fd9523e001756ce7109e639ebb54be4fcdabf))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* **heartbeat:** inject ObjectMapper into InstanceHeartbeatService ([#42](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/42)) ([0c98151](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0c981517da1f94cd10ae396e47bde2b35d0b3ba0))
|
||||||
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
* Lints ([dc224ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dc224abe26acf5361c56956006e1cc51b75b0b7e))
|
||||||
|
* **redis:** add max pool wait time and switch to ReactiveRedisDataSource for heartbeat updates ([33e5017](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e5017f51a998327b180f778f73964cc10c05d3))
|
||||||
|
* **redis:** enhance GameRedisSubscriberManager to use ReactiveRedisDataSource and improve subscription handling ([0eb752d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0eb752d4935377f75aab710b7f4eda4b29098e6a))
|
||||||
|
* **redis:** prevent concurrent Redis heartbeat refreshes using AtomicBoolean ([847b132](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/847b13202cb909d18ca3304c27ebe17ce2312b8e))
|
||||||
|
* **redis:** simplify refreshRedisHeartbeat logic and ensure proper error handling ([1813ea1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1813ea1d2d5d093f7925f87371b5e29820bf1136))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
* update documentation to reflect new functions in CoordinatorGrpcServer and InstanceRegistry ([f7ce4df](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f7ce4df595cbdc2ef84122781f4851ff140c0f44))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add CORS configuration and reorder JWT settings in application.yml ([a49f9be](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a49f9be146f04c14561c305d980846a92f8c12b2))
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-37 Quarkus integration ([#35](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/35)) ([f088c4e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f088c4e9ffcc498d3d1b6f01e8f50042d5830d55))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([33e785d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e785d22af87724839b62ae91dfe74a05b398c3))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
||||||
|
* NCS-53 changed IO to MicroService for easier scaling ([#37](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/37)) ([b5a2966](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b5a2966adafa9650f0f7d601bdeb8fdd13710327))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#48](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/48)) ([c96a09b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c96a09bb5cee59fc23205bb63baa8b217a7e1b00))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* **rule:** Rules as a microservice ([#39](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/39)) ([093134d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/093134d36c6844ba02a36a28d5d044f09291cd1d))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* **auth:** change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation ([c08d530](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c08d5303eb9e70d36c8eebf6a061ccb71e118fe5))
|
||||||
|
* **auth:** update InternalAuthFilter to use @ApplicationScoped and add index-dependency configuration ([6e0fd95](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e0fd9523e001756ce7109e639ebb54be4fcdabf))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* **heartbeat:** inject ObjectMapper into InstanceHeartbeatService ([#42](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/42)) ([0c98151](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0c981517da1f94cd10ae396e47bde2b35d0b3ba0))
|
||||||
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
* Lints ([dc224ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dc224abe26acf5361c56956006e1cc51b75b0b7e))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* NCS-85 Database Writeback fails without Logs ([#52](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/52)) ([7323908](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/73239088d985f01aa6b1067ed9097a845e471d4f))
|
||||||
|
* **redis:** add max pool wait time and switch to ReactiveRedisDataSource for heartbeat updates ([33e5017](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e5017f51a998327b180f778f73964cc10c05d3))
|
||||||
|
* **redis:** enhance GameRedisSubscriberManager to use ReactiveRedisDataSource and improve subscription handling ([0eb752d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0eb752d4935377f75aab710b7f4eda4b29098e6a))
|
||||||
|
* **redis:** prevent concurrent Redis heartbeat refreshes using AtomicBoolean ([847b132](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/847b13202cb909d18ca3304c27ebe17ce2312b8e))
|
||||||
|
* **redis:** simplify refreshRedisHeartbeat logic and ensure proper error handling ([1813ea1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1813ea1d2d5d093f7925f87371b5e29820bf1136))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
* update documentation to reflect new functions in CoordinatorGrpcServer and InstanceRegistry ([f7ce4df](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f7ce4df595cbdc2ef84122781f4851ff140c0f44))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add authentication permissions for metrics endpoints in application.yml ([04edd4d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/04edd4d6fd8a63196c36f6d67992832febc9bebb))
|
||||||
|
* add CORS configuration and reorder JWT settings in application.yml ([a49f9be](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a49f9be146f04c14561c305d980846a92f8c12b2))
|
||||||
|
* add GameRules stub with PositionStatus enum ([76d4168](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/76d4168038de23e5d6083d4e8f0504fbf31d15a3))
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add MovedInCheck/Checkmate/Stalemate MoveResult variants (stub dispatch) ([8b7ec57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8b7ec57e5ea6ee1615a1883848a426dc07d26364))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* implement clock expiry scanning and handling for game records ([#53](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/53)) ([8f9eb12](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8f9eb12f663efabe4dc72b94394438652ad0ef02))
|
||||||
|
* implement GameRules with isInCheck, legalMoves, gameStatus ([94a02ff](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/94a02ff6849436d9496c70a0f16c21666dae8e4e))
|
||||||
|
* implement legal castling ([#1](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/1)) ([00d326c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/00d326c1ba67711fbe180f04e1100c3f01dd0254))
|
||||||
|
* implement periodic scaling checks and enhance instance management in AutoScaler ([3f12f69](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f12f695f132b92f634d98df2c037292498b6e86))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-10 Implement Pawn Promotion ([#12](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/12)) ([13bfc16](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/13bfc16cfe25db78ec607db523ca6d993c13430c))
|
||||||
|
* NCS-11 50-move rule ([#9](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/9)) ([412ed98](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/412ed986a95703a3b282276540153480ceed229d))
|
||||||
|
* NCS-13 Implement Threefold Repetition ([#31](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/31)) ([767d305](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/767d3051a76c266050b6335774d66e2db2273c16))
|
||||||
|
* NCS-14 implemented insufficient moves rule ([#30](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/30)) ([b0399a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b0399a4e489950083066c9538df9a84dcc7a4613))
|
||||||
|
* NCS-16 Core Separation via Patterns ([#10](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/10)) ([1361dfc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1361dfc89553b146864fb8ff3526cf12cf3f293a))
|
||||||
|
* NCS-17 Implement basic ScalaFX UI ([#14](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/14)) ([3ff8031](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ff80318b4f16c59733a46498581a5c27f048287))
|
||||||
|
* NCS-21 Write Scripts to automate certain tasks ([#15](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/15)) ([8051871](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/80518719d536a087d339fe02530825dc07f8b388))
|
||||||
|
* NCS-25 Add linters to keep quality up ([#27](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/27)) ([fd4e67d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fd4e67d4f782a7e955822d90cb909d0a81676fb2))
|
||||||
|
* NCS-37 Quarkus integration ([#35](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/35)) ([f088c4e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f088c4e9ffcc498d3d1b6f01e8f50042d5830d55))
|
||||||
|
* NCS-40 Rework Draw System ([#34](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/34)) ([33e785d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e785d22af87724839b62ae91dfe74a05b398c3))
|
||||||
|
* NCS-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
||||||
|
* NCS-53 changed IO to MicroService for easier scaling ([#37](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/37)) ([b5a2966](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b5a2966adafa9650f0f7d601bdeb8fdd13710327))
|
||||||
|
* NCS-6 Implementing FEN & PGN ([#7](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/7)) ([f28e69d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f28e69dc181416aa2f221fdc4b45c2cda5efbf07))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#48](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/48)) ([c96a09b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c96a09bb5cee59fc23205bb63baa8b217a7e1b00))
|
||||||
|
* NCS-9 En passant implementation ([#8](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/8)) ([919beb3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/919beb3b4bfa8caf2f90976a415fe9b19b7e9747))
|
||||||
|
* **rule:** Rules as a microservice ([#39](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/39)) ([093134d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/093134d36c6844ba02a36a28d5d044f09291cd1d))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
* wire check/checkmate/stalemate into processMove and gameLoop ([5264a22](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5264a225418b885c5e6ea6411b96f85e38837f6c))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing kings to gameLoop capture test board ([aedd787](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/aedd787b77203c2af934751dba7b784eaf165032))
|
||||||
|
* **auth:** change InternalAuthFilter to use @Singleton and add HTTP tests for secret validation ([c08d530](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c08d5303eb9e70d36c8eebf6a061ccb71e118fe5))
|
||||||
|
* **auth:** update InternalAuthFilter to use @ApplicationScoped and add index-dependency configuration ([6e0fd95](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6e0fd9523e001756ce7109e639ebb54be4fcdabf))
|
||||||
|
* correct test board positions and captureOutput/withInput interaction ([f0481e2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f0481e2561b779df00925b46ee281dc36a795150))
|
||||||
|
* **heartbeat:** inject ObjectMapper into InstanceHeartbeatService ([#42](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/42)) ([0c98151](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0c981517da1f94cd10ae396e47bde2b35d0b3ba0))
|
||||||
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
* Lints ([dc224ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/dc224abe26acf5361c56956006e1cc51b75b0b7e))
|
||||||
|
* NCS-84 More Verbose Logging ([#51](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/51)) ([4ad92ab](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/4ad92ab23698267f8faa59c4e18388d4a0042cca))
|
||||||
|
* NCS-85 Database Writeback fails without Logs ([#52](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/52)) ([7323908](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/73239088d985f01aa6b1067ed9097a845e471d4f))
|
||||||
|
* **redis:** add max pool wait time and switch to ReactiveRedisDataSource for heartbeat updates ([33e5017](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/33e5017f51a998327b180f778f73964cc10c05d3))
|
||||||
|
* **redis:** enhance GameRedisSubscriberManager to use ReactiveRedisDataSource and improve subscription handling ([0eb752d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0eb752d4935377f75aab710b7f4eda4b29098e6a))
|
||||||
|
* **redis:** prevent concurrent Redis heartbeat refreshes using AtomicBoolean ([847b132](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/847b13202cb909d18ca3304c27ebe17ce2312b8e))
|
||||||
|
* **redis:** simplify refreshRedisHeartbeat logic and ensure proper error handling ([1813ea1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1813ea1d2d5d093f7925f87371b5e29820bf1136))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
* update documentation to reflect new functions in CoordinatorGrpcServer and InstanceRegistry ([f7ce4df](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f7ce4df595cbdc2ef84122781f4851ff140c0f44))
|
||||||
|
* update main class path in build configuration and adjust VCS directory mapping ([7b1f8b1](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7b1f8b117623d327232a1a92a8a44d18582e0189))
|
||||||
|
* update move validation to check for king safety ([#13](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/13)) ([e5e20c5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5e20c566e368b12ca1dc59680c34e9112bf6762))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "feat: add authentication permissions for metrics endpoints in application.yml" ([a298417](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a298417b9e4d68dc73bbf40be63d9484536e9f83))
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ nowchess:
|
|||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
http:
|
http:
|
||||||
root-path: /api
|
|
||||||
cors:
|
cors:
|
||||||
~: true
|
~: true
|
||||||
origins: ${CORS_ORIGINS}
|
origins: ${CORS_ORIGINS}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ import de.nowchess.api.board.{CastlingRights, Color, File, Piece, PieceType, Ran
|
|||||||
import de.nowchess.api.dto.*
|
import de.nowchess.api.dto.*
|
||||||
import de.nowchess.api.game.{DrawReason, GameContext, GameMode, GameResult}
|
import de.nowchess.api.game.{DrawReason, GameContext, GameMode, GameResult}
|
||||||
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
|
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
|
||||||
|
import de.nowchess.chess.registry.GameCacheDto
|
||||||
import io.quarkus.runtime.annotations.RegisterForReflection
|
import io.quarkus.runtime.annotations.RegisterForReflection
|
||||||
|
|
||||||
@RegisterForReflection(
|
@RegisterForReflection(
|
||||||
targets = Array(
|
targets = Array(
|
||||||
classOf[ApiErrorDto],
|
classOf[ApiErrorDto],
|
||||||
|
classOf[GameCacheDto],
|
||||||
classOf[ClockDto],
|
classOf[ClockDto],
|
||||||
classOf[CreateGameRequestDto],
|
classOf[CreateGameRequestDto],
|
||||||
classOf[ErrorEventDto],
|
classOf[ErrorEventDto],
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ class GameEngine(
|
|||||||
@SuppressWarnings(Array("DisableSyntax.var"))
|
@SuppressWarnings(Array("DisableSyntax.var"))
|
||||||
private var pendingTakebackRequest: Option[Color] = initialTakebackRequest
|
private var pendingTakebackRequest: Option[Color] = initialTakebackRequest
|
||||||
|
|
||||||
|
GameEngine.activeGamesCount.incrementAndGet()
|
||||||
meterRegistry.foreach { reg =>
|
meterRegistry.foreach { reg =>
|
||||||
GameEngine.activeGamesCount.incrementAndGet()
|
|
||||||
reg.counter("nowchess.games.started").increment()
|
reg.counter("nowchess.games.started").increment()
|
||||||
}
|
}
|
||||||
private def gamesCompletedCounter(result: String): Counter =
|
private def gamesCompletedCounter(result: String): Counter =
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class IoGrpcClientWrapper:
|
|||||||
CombinedExportResponse(combined.getFen, combined.getPgn)
|
CombinedExportResponse(combined.getFen, combined.getPgn)
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "IO gRPC exportCombined failed")
|
log.errorf(ex, "IO gRPC exportCombined failed")
|
||||||
// scalafix:off DisableSyntax.throw
|
// scalafix:off DisableSyntax.throw
|
||||||
throw ex
|
throw ex
|
||||||
// scalafix:on DisableSyntax.throw
|
// scalafix:on DisableSyntax.throw
|
||||||
@@ -34,7 +34,7 @@ class IoGrpcClientWrapper:
|
|||||||
try CoreProtoMapper.fromProtoGameContext(stub.importFen(ProtoImportFenRequest.newBuilder().setFen(fen).build()))
|
try CoreProtoMapper.fromProtoGameContext(stub.importFen(ProtoImportFenRequest.newBuilder().setFen(fen).build()))
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "IO gRPC importFen failed for fen %s", fen)
|
log.errorf(ex, "IO gRPC importFen failed for fen %s", fen)
|
||||||
// scalafix:off DisableSyntax.throw
|
// scalafix:off DisableSyntax.throw
|
||||||
throw ex
|
throw ex
|
||||||
// scalafix:on DisableSyntax.throw
|
// scalafix:on DisableSyntax.throw
|
||||||
@@ -43,7 +43,7 @@ class IoGrpcClientWrapper:
|
|||||||
try CoreProtoMapper.fromProtoGameContext(stub.importPgn(ProtoImportPgnRequest.newBuilder().setPgn(pgn).build()))
|
try CoreProtoMapper.fromProtoGameContext(stub.importPgn(ProtoImportPgnRequest.newBuilder().setPgn(pgn).build()))
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "IO gRPC importPgn failed")
|
log.errorf(ex, "IO gRPC importPgn failed")
|
||||||
// scalafix:off DisableSyntax.throw
|
// scalafix:off DisableSyntax.throw
|
||||||
throw ex
|
throw ex
|
||||||
// scalafix:on DisableSyntax.throw
|
// scalafix:on DisableSyntax.throw
|
||||||
@@ -52,7 +52,7 @@ class IoGrpcClientWrapper:
|
|||||||
try stub.exportFen(CoreProtoMapper.toProtoGameContext(ctx)).getValue
|
try stub.exportFen(CoreProtoMapper.toProtoGameContext(ctx)).getValue
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "IO gRPC exportFen failed")
|
log.errorf(ex, "IO gRPC exportFen failed")
|
||||||
// scalafix:off DisableSyntax.throw
|
// scalafix:off DisableSyntax.throw
|
||||||
throw ex
|
throw ex
|
||||||
// scalafix:on DisableSyntax.throw
|
// scalafix:on DisableSyntax.throw
|
||||||
@@ -61,7 +61,7 @@ class IoGrpcClientWrapper:
|
|||||||
try stub.exportPgn(CoreProtoMapper.toProtoGameContext(ctx)).getValue
|
try stub.exportPgn(CoreProtoMapper.toProtoGameContext(ctx)).getValue
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.warnf(ex, "IO gRPC exportPgn failed")
|
log.errorf(ex, "IO gRPC exportPgn failed")
|
||||||
// scalafix:off DisableSyntax.throw
|
// scalafix:off DisableSyntax.throw
|
||||||
throw ex
|
throw ex
|
||||||
// scalafix:on DisableSyntax.throw
|
// scalafix:on DisableSyntax.throw
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package de.nowchess.chess.redis
|
package de.nowchess.chess.redis
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import de.nowchess.api.dto.{GameStateEventDto, GameWritebackEventDto}
|
import de.nowchess.api.dto.{GameStateDto, GameStateEventDto, GameWritebackEventDto}
|
||||||
import de.nowchess.api.game.{CorrespondenceClockState, LiveClockState}
|
import de.nowchess.api.game.{CorrespondenceClockState, DrawReason, GameResult, LiveClockState, TimeControl, WinReason}
|
||||||
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
|
||||||
import de.nowchess.api.game.{DrawReason, GameResult, WinReason}
|
|
||||||
import de.nowchess.api.board.Color
|
import de.nowchess.api.board.Color
|
||||||
|
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
||||||
import de.nowchess.chess.observer.{GameEvent, Observer}
|
import de.nowchess.chess.observer.{GameEvent, Observer}
|
||||||
import de.nowchess.chess.registry.GameRegistry
|
import de.nowchess.chess.registry.{GameEntry, GameRegistry}
|
||||||
import de.nowchess.chess.resource.GameDtoMapper
|
import de.nowchess.chess.resource.GameDtoMapper
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import org.jboss.logging.Logger
|
import org.jboss.logging.Logger
|
||||||
@@ -26,61 +25,69 @@ class GameRedisPublisher(
|
|||||||
onGameOver: String => Unit,
|
onGameOver: String => Unit,
|
||||||
) extends Observer:
|
) extends Observer:
|
||||||
|
|
||||||
|
def emitInitialWriteback(): Unit =
|
||||||
|
try
|
||||||
|
registry.get(gameId).foreach { entry =>
|
||||||
|
val dto = GameDtoMapper.toGameStateDto(entry, ioClient)
|
||||||
|
writebackEmit(objectMapper.writeValueAsString(buildWriteback(entry, dto)))
|
||||||
|
}
|
||||||
|
catch case ex: Exception => GameRedisPublisher.log.warnf(ex, "Failed to emit initial writeback for game %s", gameId)
|
||||||
|
|
||||||
def onGameEvent(event: GameEvent): Unit =
|
def onGameEvent(event: GameEvent): Unit =
|
||||||
try
|
try
|
||||||
GameRedisPublisher.log.debugf("Publishing game event for game %s", gameId)
|
GameRedisPublisher.log.debugf("Publishing game event for game %s", gameId)
|
||||||
registry.get(gameId).foreach { entry =>
|
registry.get(gameId).foreach { entry =>
|
||||||
val dto = GameDtoMapper.toGameStateDto(entry, ioClient)
|
val dto = GameDtoMapper.toGameStateDto(entry, ioClient)
|
||||||
val json = objectMapper.writeValueAsString(GameStateEventDto(dto))
|
redis.pubsub(classOf[String]).publish(s2cTopicName, objectMapper.writeValueAsString(GameStateEventDto(dto)))
|
||||||
redis.pubsub(classOf[String]).publish(s2cTopicName, json)
|
writebackEmit(objectMapper.writeValueAsString(buildWriteback(entry, dto)))
|
||||||
|
|
||||||
val clock = entry.engine.currentClockState
|
|
||||||
val wb = GameWritebackEventDto(
|
|
||||||
gameId = gameId,
|
|
||||||
fen = dto.fen,
|
|
||||||
pgn = dto.pgn,
|
|
||||||
moveCount = entry.engine.context.moves.size,
|
|
||||||
whiteId = entry.white.id.value,
|
|
||||||
whiteName = entry.white.displayName,
|
|
||||||
blackId = entry.black.id.value,
|
|
||||||
blackName = entry.black.displayName,
|
|
||||||
mode = entry.mode.toString,
|
|
||||||
resigned = entry.resigned,
|
|
||||||
limitSeconds = entry.engine.timeControl match {
|
|
||||||
case de.nowchess.api.game.TimeControl.Clock(l, _) => Some(l); case _ => None
|
|
||||||
},
|
|
||||||
incrementSeconds = entry.engine.timeControl match {
|
|
||||||
case de.nowchess.api.game.TimeControl.Clock(_, i) => Some(i); case _ => None
|
|
||||||
},
|
|
||||||
daysPerMove = entry.engine.timeControl match {
|
|
||||||
case de.nowchess.api.game.TimeControl.Correspondence(d) => Some(d); case _ => None
|
|
||||||
},
|
|
||||||
whiteRemainingMs = clock.collect { case c: LiveClockState => c.whiteRemainingMs },
|
|
||||||
blackRemainingMs = clock.collect { case c: LiveClockState => c.blackRemainingMs },
|
|
||||||
incrementMs = clock.collect { case c: LiveClockState => c.incrementMs },
|
|
||||||
clockLastTickAt = clock.collect { case c: LiveClockState => c.lastTickAt.toEpochMilli },
|
|
||||||
clockMoveDeadline = clock.collect { case c: CorrespondenceClockState => c.moveDeadline.toEpochMilli },
|
|
||||||
clockActiveColor = clock.map(_.activeColor.label.toLowerCase),
|
|
||||||
pendingDrawOffer = entry.engine.pendingDrawOfferBy.map(_.label.toLowerCase),
|
|
||||||
result = entry.engine.context.result.map {
|
|
||||||
case GameResult.Win(Color.White, _) => "white"
|
|
||||||
case GameResult.Win(Color.Black, _) => "black"
|
|
||||||
case GameResult.Draw(_) => "draw"
|
|
||||||
},
|
|
||||||
terminationReason = entry.engine.context.result.map {
|
|
||||||
case GameResult.Win(_, WinReason.Checkmate) => "checkmate"
|
|
||||||
case GameResult.Win(_, WinReason.Resignation) => "resignation"
|
|
||||||
case GameResult.Win(_, WinReason.TimeControl) => "timeout"
|
|
||||||
case GameResult.Draw(DrawReason.Stalemate) => "stalemate"
|
|
||||||
case GameResult.Draw(DrawReason.InsufficientMaterial) => "insufficient_material"
|
|
||||||
case GameResult.Draw(DrawReason.FiftyMoveRule) => "fifty_move"
|
|
||||||
case GameResult.Draw(DrawReason.ThreefoldRepetition) => "repetition"
|
|
||||||
case GameResult.Draw(DrawReason.Agreement) => "agreement"
|
|
||||||
},
|
|
||||||
redoStack = entry.engine.redoStackMoves.map(GameDtoMapper.moveToUci),
|
|
||||||
pendingTakebackRequest = entry.engine.pendingTakebackRequestBy.map(_.label.toLowerCase),
|
|
||||||
)
|
|
||||||
writebackEmit(objectMapper.writeValueAsString(wb))
|
|
||||||
if entry.engine.context.result.isDefined then onGameOver(gameId)
|
if entry.engine.context.result.isDefined then onGameOver(gameId)
|
||||||
}
|
}
|
||||||
catch case ex: Exception => GameRedisPublisher.log.warnf(ex, "Failed to publish game event for game %s", gameId)
|
catch case ex: Exception => GameRedisPublisher.log.warnf(ex, "Failed to publish game event for game %s", gameId)
|
||||||
|
|
||||||
|
private def buildWriteback(entry: GameEntry, dto: GameStateDto): GameWritebackEventDto =
|
||||||
|
val clock = entry.engine.currentClockState
|
||||||
|
GameWritebackEventDto(
|
||||||
|
gameId = gameId,
|
||||||
|
fen = dto.fen,
|
||||||
|
pgn = dto.pgn,
|
||||||
|
moveCount = entry.engine.context.moves.size,
|
||||||
|
whiteId = entry.white.id.value,
|
||||||
|
whiteName = entry.white.displayName,
|
||||||
|
blackId = entry.black.id.value,
|
||||||
|
blackName = entry.black.displayName,
|
||||||
|
mode = entry.mode.toString,
|
||||||
|
resigned = entry.resigned,
|
||||||
|
limitSeconds = entry.engine.timeControl match {
|
||||||
|
case TimeControl.Clock(l, _) => Some(l); case _ => None
|
||||||
|
},
|
||||||
|
incrementSeconds = entry.engine.timeControl match {
|
||||||
|
case TimeControl.Clock(_, i) => Some(i); case _ => None
|
||||||
|
},
|
||||||
|
daysPerMove = entry.engine.timeControl match {
|
||||||
|
case TimeControl.Correspondence(d) => Some(d); case _ => None
|
||||||
|
},
|
||||||
|
whiteRemainingMs = clock.collect { case c: LiveClockState => c.whiteRemainingMs },
|
||||||
|
blackRemainingMs = clock.collect { case c: LiveClockState => c.blackRemainingMs },
|
||||||
|
incrementMs = clock.collect { case c: LiveClockState => c.incrementMs },
|
||||||
|
clockLastTickAt = clock.collect { case c: LiveClockState => c.lastTickAt.toEpochMilli },
|
||||||
|
clockMoveDeadline = clock.collect { case c: CorrespondenceClockState => c.moveDeadline.toEpochMilli },
|
||||||
|
clockActiveColor = clock.map(_.activeColor.label.toLowerCase),
|
||||||
|
pendingDrawOffer = entry.engine.pendingDrawOfferBy.map(_.label.toLowerCase),
|
||||||
|
result = entry.engine.context.result.map {
|
||||||
|
case GameResult.Win(Color.White, _) => "white"
|
||||||
|
case GameResult.Win(Color.Black, _) => "black"
|
||||||
|
case GameResult.Draw(_) => "draw"
|
||||||
|
},
|
||||||
|
terminationReason = entry.engine.context.result.map {
|
||||||
|
case GameResult.Win(_, WinReason.Checkmate) => "checkmate"
|
||||||
|
case GameResult.Win(_, WinReason.Resignation) => "resignation"
|
||||||
|
case GameResult.Win(_, WinReason.TimeControl) => "timeout"
|
||||||
|
case GameResult.Draw(DrawReason.Stalemate) => "stalemate"
|
||||||
|
case GameResult.Draw(DrawReason.InsufficientMaterial) => "insufficient_material"
|
||||||
|
case GameResult.Draw(DrawReason.FiftyMoveRule) => "fifty_move"
|
||||||
|
case GameResult.Draw(DrawReason.ThreefoldRepetition) => "repetition"
|
||||||
|
case GameResult.Draw(DrawReason.Agreement) => "agreement"
|
||||||
|
},
|
||||||
|
redoStack = entry.engine.redoStackMoves.map(GameDtoMapper.moveToUci),
|
||||||
|
pendingTakebackRequest = entry.engine.pendingTakebackRequestBy.map(_.label.toLowerCase),
|
||||||
|
)
|
||||||
|
|||||||
+36
-11
@@ -13,6 +13,7 @@ import de.nowchess.chess.service.InstanceHeartbeatService
|
|||||||
import io.quarkus.redis.datasource.ReactiveRedisDataSource
|
import io.quarkus.redis.datasource.ReactiveRedisDataSource
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import io.quarkus.redis.datasource.pubsub.ReactivePubSubCommands
|
import io.quarkus.redis.datasource.pubsub.ReactivePubSubCommands
|
||||||
|
import jakarta.annotation.PostConstruct
|
||||||
import jakarta.annotation.PreDestroy
|
import jakarta.annotation.PreDestroy
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
import jakarta.enterprise.inject.Instance
|
import jakarta.enterprise.inject.Instance
|
||||||
@@ -45,6 +46,30 @@ class GameRedisSubscriberManager:
|
|||||||
private val c2sListeners = new ConcurrentHashMap[String, ReactivePubSubCommands.ReactiveRedisSubscriber]()
|
private val c2sListeners = new ConcurrentHashMap[String, ReactivePubSubCommands.ReactiveRedisSubscriber]()
|
||||||
private val s2cObservers = new ConcurrentHashMap[String, Observer]()
|
private val s2cObservers = new ConcurrentHashMap[String, Observer]()
|
||||||
|
|
||||||
|
// scalafix:off DisableSyntax.var
|
||||||
|
private var clockExpireSubscriber: Option[ReactivePubSubCommands.ReactiveRedisSubscriber] = None
|
||||||
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
|
private def clockExpireChannel: String = s"${redisConfig.prefix}:game:clock:expire"
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
def subscribeClockExpiry(): Unit =
|
||||||
|
val handler: Consumer[String] = gameId => handleClockExpiry(gameId)
|
||||||
|
try
|
||||||
|
val subscriber = reactiveRedis
|
||||||
|
.pubsub(classOf[String])
|
||||||
|
.subscribe(clockExpireChannel, handler)
|
||||||
|
.await()
|
||||||
|
.atMost(java.time.Duration.ofSeconds(5))
|
||||||
|
clockExpireSubscriber = Some(subscriber)
|
||||||
|
log.infof("Subscribed to clock expiry channel %s", clockExpireChannel)
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Failed to subscribe to clock expiry channel")
|
||||||
|
|
||||||
|
private def handleClockExpiry(gameId: String): Unit =
|
||||||
|
if !s2cObservers.containsKey(gameId) then
|
||||||
|
log.infof("Clock expired for game %s — loading engine to enforce timeout", gameId)
|
||||||
|
subscribeGame(gameId)
|
||||||
|
|
||||||
private def c2sTopic(gameId: String): String =
|
private def c2sTopic(gameId: String): String =
|
||||||
s"${redisConfig.prefix}:game:$gameId:c2s"
|
s"${redisConfig.prefix}:game:$gameId:c2s"
|
||||||
|
|
||||||
@@ -65,20 +90,19 @@ class GameRedisSubscriberManager:
|
|||||||
)
|
)
|
||||||
s2cObservers.put(gameId, obs)
|
s2cObservers.put(gameId, obs)
|
||||||
registry.get(gameId).foreach(_.engine.subscribe(obs))
|
registry.get(gameId).foreach(_.engine.subscribe(obs))
|
||||||
|
obs.emitInitialWriteback()
|
||||||
heartbeatServiceOpt.foreach(_.addGameSubscription(gameId))
|
heartbeatServiceOpt.foreach(_.addGameSubscription(gameId))
|
||||||
|
|
||||||
val handler: Consumer[String] = msg => handleC2sMessage(gameId, msg)
|
val handler: Consumer[String] = msg => handleC2sMessage(gameId, msg)
|
||||||
reactiveRedis
|
try
|
||||||
.pubsub(classOf[String])
|
val subscriber = reactiveRedis
|
||||||
.subscribe(c2sTopic(gameId), handler)
|
.pubsub(classOf[String])
|
||||||
.subscribe()
|
.subscribe(c2sTopic(gameId), handler)
|
||||||
.`with`(
|
.await()
|
||||||
subscriber => {
|
.atMost(java.time.Duration.ofSeconds(5))
|
||||||
c2sListeners.put(gameId, subscriber)
|
c2sListeners.put(gameId, subscriber)
|
||||||
log.debugf("Subscribed to game %s", gameId)
|
log.debugf("Subscribed to game %s", gameId)
|
||||||
},
|
catch case ex: Exception => log.warnf(ex, "Redis subscription failed for game %s", gameId)
|
||||||
failure => log.warnf(failure, "Redis subscription failed for game %s", gameId),
|
|
||||||
)
|
|
||||||
|
|
||||||
def unsubscribeGame(gameId: String): Unit =
|
def unsubscribeGame(gameId: String): Unit =
|
||||||
Option(c2sListeners.remove(gameId)).foreach { subscriber =>
|
Option(c2sListeners.remove(gameId)).foreach { subscriber =>
|
||||||
@@ -158,5 +182,6 @@ class GameRedisSubscriberManager:
|
|||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
def cleanup(): Unit =
|
def cleanup(): Unit =
|
||||||
|
clockExpireSubscriber.foreach(_.unsubscribe(clockExpireChannel).await().indefinitely())
|
||||||
c2sListeners.forEach((gameId, subscriber) => subscriber.unsubscribe(c2sTopic(gameId)).await().indefinitely())
|
c2sListeners.forEach((gameId, subscriber) => subscriber.unsubscribe(c2sTopic(gameId)).await().indefinitely())
|
||||||
s2cObservers.forEach((gameId, obs) => registry.get(gameId).foreach(_.engine.unsubscribe(obs)))
|
s2cObservers.forEach((gameId, obs) => registry.get(gameId).foreach(_.engine.unsubscribe(obs)))
|
||||||
|
|||||||
+1
-1
@@ -199,7 +199,7 @@ class InstanceHeartbeatService:
|
|||||||
val json = mapper.writeValueAsString(metadata)
|
val json = mapper.writeValueAsString(metadata)
|
||||||
reactiveRedis
|
reactiveRedis
|
||||||
.value(classOf[String])
|
.value(classOf[String])
|
||||||
.setex(key, 5L, json)
|
.setex(key, 15L, json)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
.`with`(
|
.`with`(
|
||||||
_ => redisHeartbeatPending.set(false),
|
_ => redisHeartbeatPending.set(false),
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=37
|
MINOR=42
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -187,3 +187,72 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* **config:** update application.yml to nest HTTP port configuration ([3efebd5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3efebd5ed0493159c51f7246d18d59bac58cf875))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* **config:** update application.yml to nest HTTP port configuration ([3efebd5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3efebd5ed0493159c51f7246d18d59bac58cf875))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* NCS-85 Database Writeback fails without Logs ([#52](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/52)) ([7323908](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/73239088d985f01aa6b1067ed9097a845e471d4f))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
## (2026-05-16)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* **config:** update application.yml to nest HTTP port configuration ([3efebd5](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3efebd5ed0493159c51f7246d18d59bac58cf875))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* implement clock expiry scanning and handling for game records ([#53](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/53)) ([8f9eb12](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8f9eb12f663efabe4dc72b94394438652ad0ef02))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* NCS-85 Database Writeback fails without Logs ([#52](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/52)) ([7323908](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/73239088d985f01aa6b1067ed9097a845e471d4f))
|
||||||
|
* **redis:** update Redis configuration with max pool size and waiting parameters ([5baf6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5baf6a7cdbea484fc49c02e2b5a1c3919b7fa2c4))
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ dependencies {
|
|||||||
implementation("io.quarkus:quarkus-opentelemetry")
|
implementation("io.quarkus:quarkus-opentelemetry")
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
||||||
implementation("io.quarkus:quarkus-redis-client")
|
implementation("io.quarkus:quarkus-redis-client")
|
||||||
|
implementation("io.quarkus:quarkus-scheduler")
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ nowchess:
|
|||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
http:
|
|
||||||
root-path: /api/store
|
|
||||||
log:
|
log:
|
||||||
console:
|
console:
|
||||||
json: true
|
json: true
|
||||||
|
|||||||
+12
-3
@@ -7,8 +7,9 @@ import io.quarkus.redis.datasource.RedisDataSource
|
|||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
|
import org.jboss.logging.Logger
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import scala.util.Try
|
import scala.util.{Failure, Success, Try}
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
@@ -20,10 +21,18 @@ class GameWritebackStreamListener:
|
|||||||
@Inject var writebackService: GameWritebackService = uninitialized
|
@Inject var writebackService: GameWritebackService = uninitialized
|
||||||
// scalafix:on
|
// scalafix:on
|
||||||
|
|
||||||
|
private val log = Logger.getLogger(classOf[GameWritebackStreamListener])
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
def startListening(): Unit =
|
def startListening(): Unit =
|
||||||
val handler: Consumer[String] = json =>
|
val handler: Consumer[String] = json =>
|
||||||
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])).toOption
|
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])) match
|
||||||
.foreach(writebackService.writeBack)
|
case Failure(ex) =>
|
||||||
|
log.errorf(ex, "Failed to parse game-writeback event: %s", json)
|
||||||
|
case Success(event) =>
|
||||||
|
Try(writebackService.writeBack(event)) match
|
||||||
|
case Failure(ex) =>
|
||||||
|
log.errorf(ex, "Failed to write back game event for gameId=%s", event.gameId)
|
||||||
|
case Success(_) => ()
|
||||||
redis.pubsub(classOf[String]).subscribe("game-writeback", handler)
|
redis.pubsub(classOf[String]).subscribe("game-writeback", handler)
|
||||||
()
|
()
|
||||||
|
|||||||
@@ -34,6 +34,19 @@ class GameRecordRepository:
|
|||||||
.asScala
|
.asScala
|
||||||
.toList
|
.toList
|
||||||
|
|
||||||
|
def findExpiredLiveClockGames(nowMs: Long): List[GameRecord] =
|
||||||
|
em.createQuery(
|
||||||
|
"SELECT g FROM GameRecord g WHERE g.result IS NULL AND g.clockLastTickAt IS NOT NULL AND g.whiteRemainingMs IS NOT NULL",
|
||||||
|
classOf[GameRecord],
|
||||||
|
).getResultList
|
||||||
|
.asScala
|
||||||
|
.toList
|
||||||
|
.filter { g =>
|
||||||
|
val remaining =
|
||||||
|
if g.clockActiveColor == "white" then g.whiteRemainingMs.longValue else g.blackRemainingMs.longValue
|
||||||
|
g.clockLastTickAt.longValue + remaining < nowMs
|
||||||
|
}
|
||||||
|
|
||||||
def findByPlayerIdRunning(playerId: String, offset: Int, limit: Int): List[GameRecord] =
|
def findByPlayerIdRunning(playerId: String, offset: Int, limit: Int): List[GameRecord] =
|
||||||
em.createQuery(
|
em.createQuery(
|
||||||
"SELECT g FROM GameRecord g WHERE g.whiteId = :id OR g.blackId = :id AND g.result = null ORDER BY g.updatedAt DESC",
|
"SELECT g FROM GameRecord g WHERE g.whiteId = :id OR g.blackId = :id AND g.result = null ORDER BY g.updatedAt DESC",
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package de.nowchess.store.service
|
||||||
|
|
||||||
|
import de.nowchess.store.config.RedisConfig
|
||||||
|
import de.nowchess.store.repository.GameRecordRepository
|
||||||
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
|
import io.quarkus.scheduler.Scheduled
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
import org.jboss.logging.Logger
|
||||||
|
import scala.compiletime.uninitialized
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
class ClockExpiryScanner:
|
||||||
|
@Inject
|
||||||
|
// scalafix:off DisableSyntax.var
|
||||||
|
var repository: GameRecordRepository = uninitialized
|
||||||
|
@Inject var redis: RedisDataSource = uninitialized
|
||||||
|
@Inject var redisConfig: RedisConfig = uninitialized
|
||||||
|
// scalafix:on
|
||||||
|
|
||||||
|
private val log = Logger.getLogger(classOf[ClockExpiryScanner])
|
||||||
|
|
||||||
|
private def clockExpireChannel: String = s"${redisConfig.prefix}:game:clock:expire"
|
||||||
|
|
||||||
|
@Scheduled(every = "30s")
|
||||||
|
def scan(): Unit =
|
||||||
|
try
|
||||||
|
val nowMs = System.currentTimeMillis()
|
||||||
|
val expired = repository.findExpiredLiveClockGames(nowMs)
|
||||||
|
if expired.nonEmpty then
|
||||||
|
log.infof("Found %d games with expired clocks", expired.size)
|
||||||
|
expired.foreach { record =>
|
||||||
|
log.infof("Publishing clock expiry for game %s", record.gameId)
|
||||||
|
redis.pubsub(classOf[String]).publish(clockExpireChannel, record.gameId)
|
||||||
|
}
|
||||||
|
catch case ex: Exception => log.warnf(ex, "Clock expiry scan failed")
|
||||||
@@ -8,6 +8,7 @@ import jakarta.annotation.PostConstruct
|
|||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
import jakarta.transaction.Transactional
|
import jakarta.transaction.Transactional
|
||||||
|
import org.jboss.logging.Logger
|
||||||
|
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@@ -15,6 +16,8 @@ import java.time.Instant
|
|||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
class GameWritebackService:
|
class GameWritebackService:
|
||||||
|
|
||||||
|
private val log = Logger.getLogger(classOf[GameWritebackService])
|
||||||
|
|
||||||
// scalafix:off DisableSyntax.var
|
// scalafix:off DisableSyntax.var
|
||||||
@Inject
|
@Inject
|
||||||
var repository: GameRecordRepository = uninitialized
|
var repository: GameRecordRepository = uninitialized
|
||||||
@@ -46,12 +49,15 @@ class GameWritebackService:
|
|||||||
private def doWriteBack(event: GameWritebackEventDto): Unit =
|
private def doWriteBack(event: GameWritebackEventDto): Unit =
|
||||||
repository.findByGameId(event.gameId) match
|
repository.findByGameId(event.gameId) match
|
||||||
case None =>
|
case None =>
|
||||||
|
log.infof("Creating game record for gameId=%s", event.gameId)
|
||||||
createRecord(event)
|
createRecord(event)
|
||||||
gamesWrittenCounter("create").increment()
|
gamesWrittenCounter("create").increment()
|
||||||
case Some(r) if event.moveCount > r.moveCount || event.pgn != r.pgn =>
|
case Some(r) if event.moveCount > r.moveCount || event.pgn != r.pgn =>
|
||||||
|
log.infof("Updating game record for gameId=%s moveCount=%d", event.gameId, event.moveCount)
|
||||||
updateRecord(r, event)
|
updateRecord(r, event)
|
||||||
gamesWrittenCounter("update").increment()
|
gamesWrittenCounter("update").increment()
|
||||||
case _ =>
|
case _ =>
|
||||||
|
log.debugf("Skipping writeback for gameId=%s (no change)", event.gameId)
|
||||||
writebackSkipped.increment()
|
writebackSkipped.increment()
|
||||||
|
|
||||||
private def createRecord(event: GameWritebackEventDto): Unit =
|
private def createRecord(event: GameWritebackEventDto): Unit =
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=13
|
MINOR=16
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -178,3 +178,29 @@
|
|||||||
### Reverts
|
### Reverts
|
||||||
|
|
||||||
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-05-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add initialization metrics for various services ([d438e97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d438e97f32bdde0bfc63c1b4a8cc810cdd093166))
|
||||||
|
* add OpenTelemetry trace configuration with parentbased sampler ([3904d5a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3904d5ad8ad4930ddee65287a7bfab785a6148f5))
|
||||||
|
* **config:** update application.yml for PostgreSQL and remove staging/production configurations ([2404e61](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2404e6164c3b50ffccbea5238d636060d6abe4d6))
|
||||||
|
* **config:** update application.yml for staging and production environments ([6113432](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6113432a14c476a3a0dfc0d449e17d023697f2ba))
|
||||||
|
* configure logging and add OpenTelemetry support ([#49](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/49)) ([d57c488](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d57c4886612d1d92da0e1b79209fc83e6ef537a1))
|
||||||
|
* **docker:** add .dockerignore and .gitignore files for build exclusions ([c987d8e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c987d8e258c0e6c4cfbdaa8381c64c410d7a2b83))
|
||||||
|
* **docker:** add Dockerfiles for building Quarkus application in native and JVM modes ([3f2d2bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3f2d2bb4c97fa8cddba66e1da4427c54236dfeed))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([34b9933](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/34b993304670cf2aa62cd2f6460cee7b9864b08e))
|
||||||
|
* **docker:** add Dockerfiles for Quarkus application in JVM and native modes ([e5fe7d0](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e5fe7d07a58e018151bb24f4ee37c06e72608ded))
|
||||||
|
* **logging:** add DEBUG/INFO/WARN logging across services (NCS-72) ([#41](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/41)) ([804a4bf](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/804a4bf179e3dfb19e2be4390e7e543caf5237c6))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#46](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/46)) ([649566e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/649566eb3fcf38f91c8896a739f74ea318af312d))
|
||||||
|
* NCS-78 Add Traceability to the Applications ([#47](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/47)) ([87dfc6c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87dfc6c2bcce7f7d58fc641bd8d468a2e584c108))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
* update application.yml with new API root paths and add Micrometer and OpenTelemetry dependencies ([72ce262](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/72ce262bc491f94297700e6002fb5d0812e2cc2a))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove unused HTTP root-path configurations from application.yml ([3ed3e59](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/3ed3e59ee456d54cd3d65ece4f36623e256b9736))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ nowchess:
|
|||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
http:
|
|
||||||
root-path: /ws
|
|
||||||
log:
|
log:
|
||||||
console:
|
console:
|
||||||
json: true
|
json: true
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=13
|
MINOR=14
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
Reference in New Issue
Block a user