Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3bda9466b5 |
@@ -235,10 +235,10 @@
|
|||||||
- function rebalanceInterval
|
- function rebalanceInterval
|
||||||
- function rebalanceMinInterval
|
- function rebalanceMinInterval
|
||||||
- function heartbeatTtl
|
- function heartbeatTtl
|
||||||
- _...14 more_
|
- _...12 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, function hasActiveStream
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
||||||
- `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,7 +256,6 @@
|
|||||||
- `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
|
||||||
@@ -264,7 +263,6 @@
|
|||||||
- 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
|
||||||
@@ -274,23 +272,21 @@
|
|||||||
- 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
|
||||||
- _...4 more_
|
- function updateInstanceFromRedis
|
||||||
|
- _...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
|
||||||
|
|||||||
+5
-9
@@ -179,10 +179,10 @@
|
|||||||
- function rebalanceInterval
|
- function rebalanceInterval
|
||||||
- function rebalanceMinInterval
|
- function rebalanceMinInterval
|
||||||
- function heartbeatTtl
|
- function heartbeatTtl
|
||||||
- _...14 more_
|
- _...12 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, function hasActiveStream
|
- `modules/coordinator/src/main/scala/de/nowchess/coordinator/grpc/CoordinatorGrpcServer.scala` — class CoordinatorGrpcServer
|
||||||
- `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,7 +200,6 @@
|
|||||||
- `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
|
||||||
@@ -208,7 +207,6 @@
|
|||||||
- 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
|
||||||
@@ -218,23 +216,21 @@
|
|||||||
- 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
|
||||||
- _...4 more_
|
- function updateInstanceFromRedis
|
||||||
|
- _...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
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ post {
|
|||||||
auth: inherit
|
auth: inherit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
timeout: 0
|
||||||
|
}
|
||||||
|
|
||||||
headers {
|
headers {
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
@@ -17,20 +22,9 @@ headers {
|
|||||||
|
|
||||||
body:json {
|
body:json {
|
||||||
{
|
{
|
||||||
"color": "random",
|
|
||||||
"timeControl": {
|
"timeControl": {
|
||||||
"limitSeconds": 600,
|
"limitSeconds": 600,
|
||||||
"incrementSeconds": 5
|
"incrementSeconds": 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vars:pre-request {
|
|
||||||
username: bdc
|
|
||||||
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJub3djaGVzcyIsInN1YiI6ImY3MGQxNDIwLTdhZmEtNGVjMy05Mzg1LWViYWU0N2U3NGY4OCIsInVzZXJuYW1lIjoicGxheWVyMSIsImlhdCI6MTc3OTE5MjkwOCwiZXhwIjoxNzc5MTkzMjA4LCJqdGkiOiJkMDhlZmRhMi01ZjliLTQyNjgtOGM3MC1iNDA2OTViNDhiMTUifQ.q68R2bUdRQ5QwEIfcP0d2g_Wac94qd4K6BzP-PC94x-tDpT3leUY8ZpqY6YzoNv-ywp5sm47-WC539DyUqdzDgPVLLSmOMjRxG-HpaNdXwsXlp8_C7KGlgkK_XSMa3Gq6S4AfUbaXbRhPg5NZz2MRosu0BY2ed0ISvmEfX5XEdBRlKgD14BIKAsEFv3tHtarFS1RGpcSoHV2oeIk_m-VHUC78N-ciNHmBH6mZna_fVHgMocOIrEsTZuUms0Zacmebvh2tAcf36xux1Bm2awJff19zReD-A2o9jucrKcM3Im5BJ6JtuWAsHEae9KLmuol6S2pldvNOmUn3egFUYz0yQ
|
|
||||||
}
|
|
||||||
|
|
||||||
settings {
|
|
||||||
encodeUrl: true
|
|
||||||
timeout: 0
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
# 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 |
|
||||||
@@ -224,127 +224,3 @@
|
|||||||
|
|
||||||
* 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))
|
|
||||||
## (2026-05-19)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **account:** implement token pair handling for login and refresh endpoints ([9296db8](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9296db88b7131bbda9b9b0da65c327ef9063ee31))
|
|
||||||
* 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))
|
|
||||||
* **tests:** update token path to accessToken in ChallengeResourceTest ([354db11](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/354db11972342c47a1034303c11bccfb92e60109))
|
|
||||||
|
|
||||||
### 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-21)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **account:** implement token pair handling for login and refresh endpoints ([9296db8](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9296db88b7131bbda9b9b0da65c327ef9063ee31))
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* **account:** configure JDBC connection pool size to prevent exhaustion under load ([29072ef](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/29072efbfb1cfa1c3b1a85b4c1a587c971d245f9))
|
|
||||||
* **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))
|
|
||||||
* **tests:** update token path to accessToken in ChallengeResourceTest ([354db11](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/354db11972342c47a1034303c11bccfb92e60109))
|
|
||||||
|
|
||||||
### 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,6 +57,8 @@ nowchess:
|
|||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
|
http:
|
||||||
|
root-path: /api/account
|
||||||
log:
|
log:
|
||||||
console:
|
console:
|
||||||
json: true
|
json: true
|
||||||
@@ -76,9 +78,6 @@ nowchess:
|
|||||||
password: ${DB_PASSWORD}
|
password: ${DB_PASSWORD}
|
||||||
jdbc:
|
jdbc:
|
||||||
url: ${DB_URL}
|
url: ${DB_URL}
|
||||||
min-size: 10
|
|
||||||
max-size: 50
|
|
||||||
acquisition-timeout: 30
|
|
||||||
hibernate-orm:
|
hibernate-orm:
|
||||||
schema-management:
|
schema-management:
|
||||||
strategy: update
|
strategy: update
|
||||||
|
|||||||
+1
-2
@@ -25,8 +25,7 @@ import io.quarkus.runtime.annotations.RegisterForReflection
|
|||||||
classOf[DeclineReason],
|
classOf[DeclineReason],
|
||||||
classOf[TimeControl],
|
classOf[TimeControl],
|
||||||
classOf[LoginRequest],
|
classOf[LoginRequest],
|
||||||
classOf[RefreshRequest],
|
classOf[TokenResponse],
|
||||||
classOf[TokenPairResponse],
|
|
||||||
classOf[PlayerInfo],
|
classOf[PlayerInfo],
|
||||||
classOf[PublicAccountDto],
|
classOf[PublicAccountDto],
|
||||||
classOf[BotAccountDto],
|
classOf[BotAccountDto],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import scala.compiletime.uninitialized
|
|||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import scala.Conversion
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "challenges")
|
@Table(name = "challenges")
|
||||||
@@ -33,14 +34,13 @@ class Challenge extends PanacheEntityBase:
|
|||||||
@Column(nullable = true, columnDefinition = "varchar(255)")
|
@Column(nullable = true, columnDefinition = "varchar(255)")
|
||||||
var declineReason: DeclineReason = uninitialized
|
var declineReason: DeclineReason = uninitialized
|
||||||
|
|
||||||
@Column(nullable = true)
|
var timeControlType: String = uninitialized
|
||||||
var limitSeconds: java.lang.Integer = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = true)
|
@Column(nullable = true)
|
||||||
var incrementSeconds: java.lang.Integer = uninitialized
|
var timeControlLimit: java.lang.Integer = uninitialized
|
||||||
|
|
||||||
@Column(nullable = true)
|
@Column(nullable = true)
|
||||||
var daysPerMove: java.lang.Integer = uninitialized
|
var timeControlIncrement: java.lang.Integer = uninitialized
|
||||||
|
|
||||||
var createdAt: Instant = uninitialized
|
var createdAt: Instant = uninitialized
|
||||||
|
|
||||||
@@ -52,6 +52,5 @@ class Challenge extends PanacheEntityBase:
|
|||||||
|
|
||||||
def gameIdOpt: Option[String] = Option(gameId)
|
def gameIdOpt: Option[String] = Option(gameId)
|
||||||
def declineReasonOpt: Option[DeclineReason] = Option(declineReason)
|
def declineReasonOpt: Option[DeclineReason] = Option(declineReason)
|
||||||
def limitSecondsOpt: Option[Int] = Option(limitSeconds).map(_.intValue())
|
def timeControlLimitOpt: Option[Int] = Option(timeControlLimit).map(_.intValue())
|
||||||
def incrementSecondsOpt: Option[Int] = Option(incrementSeconds).map(_.intValue())
|
def timeControlIncrementOpt: Option[Int] = Option(timeControlIncrement).map(_.intValue())
|
||||||
def daysPerMoveOpt: Option[Int] = Option(daysPerMove).map(_.intValue())
|
|
||||||
|
|||||||
@@ -4,15 +4,13 @@ case class RegisterRequest(username: String, email: String, password: String)
|
|||||||
|
|
||||||
case class LoginRequest(username: String, password: String)
|
case class LoginRequest(username: String, password: String)
|
||||||
|
|
||||||
case class RefreshRequest(refreshToken: String)
|
case class TokenResponse(token: String)
|
||||||
|
|
||||||
case class TokenPairResponse(accessToken: String, refreshToken: String)
|
|
||||||
|
|
||||||
case class PlayerInfo(id: String, name: String, rating: Int)
|
case class PlayerInfo(id: String, name: String, rating: Int)
|
||||||
|
|
||||||
case class PublicAccountDto(id: String, username: String, rating: Int, createdAt: String)
|
case class PublicAccountDto(id: String, username: String, rating: Int, createdAt: String)
|
||||||
|
|
||||||
case class TimeControlDto(limitSeconds: Option[Int], incrementSeconds: Option[Int], daysPerMove: Option[Int])
|
case class TimeControlDto(`type`: String, limit: Option[Int], increment: Option[Int])
|
||||||
|
|
||||||
case class ChallengeRequest(color: String, timeControl: TimeControlDto)
|
case class ChallengeRequest(color: String, timeControl: TimeControlDto)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ enum AccountError:
|
|||||||
case UsernameTaken(username: String)
|
case UsernameTaken(username: String)
|
||||||
case EmailAlreadyRegistered(email: String)
|
case EmailAlreadyRegistered(email: String)
|
||||||
case InvalidCredentials
|
case InvalidCredentials
|
||||||
case InvalidRefreshToken
|
|
||||||
case UserNotFound
|
case UserNotFound
|
||||||
case BotNotFound
|
case BotNotFound
|
||||||
case BotLimitExceeded
|
case BotLimitExceeded
|
||||||
@@ -16,7 +15,6 @@ enum AccountError:
|
|||||||
case UsernameTaken(u) => s"Username '$u' is already taken"
|
case UsernameTaken(u) => s"Username '$u' is already taken"
|
||||||
case EmailAlreadyRegistered(e) => s"Email '$e' is already registered"
|
case EmailAlreadyRegistered(e) => s"Email '$e' is already registered"
|
||||||
case InvalidCredentials => "Invalid credentials"
|
case InvalidCredentials => "Invalid credentials"
|
||||||
case InvalidRefreshToken => "Invalid or expired refresh token"
|
|
||||||
case UserNotFound => "User not found"
|
case UserNotFound => "User not found"
|
||||||
case BotNotFound => "Bot account not found"
|
case BotNotFound => "Bot account not found"
|
||||||
case BotLimitExceeded => "Maximum of 5 bot accounts per user exceeded"
|
case BotLimitExceeded => "Maximum of 5 bot accounts per user exceeded"
|
||||||
|
|||||||
@@ -40,19 +40,8 @@ class AccountResource:
|
|||||||
@Path("/login")
|
@Path("/login")
|
||||||
def login(req: LoginRequest): Response =
|
def login(req: LoginRequest): Response =
|
||||||
accountService.login(req) match
|
accountService.login(req) match
|
||||||
case Right((accessToken, refreshToken)) =>
|
case Right(token) =>
|
||||||
Response.ok(TokenPairResponse(accessToken, refreshToken)).build()
|
Response.ok(TokenResponse(token)).build()
|
||||||
case Left(AccountError.UserBanned) =>
|
|
||||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.UserBanned.message)).build()
|
|
||||||
case Left(error) =>
|
|
||||||
Response.status(Response.Status.UNAUTHORIZED).entity(ErrorDto(error.message)).build()
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/refresh")
|
|
||||||
def refresh(req: RefreshRequest): Response =
|
|
||||||
accountService.refresh(req.refreshToken) match
|
|
||||||
case Right((accessToken, refreshToken)) =>
|
|
||||||
Response.ok(TokenPairResponse(accessToken, refreshToken)).build()
|
|
||||||
case Left(AccountError.UserBanned) =>
|
case Left(AccountError.UserBanned) =>
|
||||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.UserBanned.message)).build()
|
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto(AccountError.UserBanned.message)).build()
|
||||||
case Left(error) =>
|
case Left(error) =>
|
||||||
|
|||||||
+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.errorf(ex, "Failed to notify bot for game %s", id)
|
catch case ex: Exception => log.warnf(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))
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import de.nowchess.account.error.AccountError
|
|||||||
import de.nowchess.account.repository.{BotAccountRepository, OfficialBotAccountRepository, UserAccountRepository}
|
import de.nowchess.account.repository.{BotAccountRepository, OfficialBotAccountRepository, UserAccountRepository}
|
||||||
import io.micrometer.core.instrument.MeterRegistry
|
import io.micrometer.core.instrument.MeterRegistry
|
||||||
import io.quarkus.elytron.security.common.BcryptUtil
|
import io.quarkus.elytron.security.common.BcryptUtil
|
||||||
import io.smallrye.jwt.auth.principal.JWTParser
|
|
||||||
import io.smallrye.jwt.build.Jwt
|
import io.smallrye.jwt.build.Jwt
|
||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
@@ -35,9 +34,6 @@ class AccountService:
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
var meterRegistry: MeterRegistry = uninitialized
|
var meterRegistry: MeterRegistry = uninitialized
|
||||||
|
|
||||||
@Inject
|
|
||||||
var jwtParser: JWTParser = uninitialized
|
|
||||||
// scalafix:on
|
// scalafix:on
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@@ -70,7 +66,7 @@ class AccountService:
|
|||||||
log.infof("User %s registered successfully", req.username)
|
log.infof("User %s registered successfully", req.username)
|
||||||
Right(account)
|
Right(account)
|
||||||
|
|
||||||
def login(req: LoginRequest): Either[AccountError, (String, String)] =
|
def login(req: LoginRequest): Either[AccountError, String] =
|
||||||
val result = authenticateUser(req)
|
val result = authenticateUser(req)
|
||||||
result match
|
result match
|
||||||
case Right(_) => meterRegistry.counter("nowchess.auth.logins", "result", "success").increment()
|
case Right(_) => meterRegistry.counter("nowchess.auth.logins", "result", "success").increment()
|
||||||
@@ -79,7 +75,7 @@ class AccountService:
|
|||||||
meterRegistry.counter("nowchess.auth.login.failures", "reason", loginFailureReason(error)).increment()
|
meterRegistry.counter("nowchess.auth.login.failures", "reason", loginFailureReason(error)).increment()
|
||||||
result
|
result
|
||||||
|
|
||||||
private def authenticateUser(req: LoginRequest): Either[AccountError, (String, String)] =
|
private def authenticateUser(req: LoginRequest): Either[AccountError, String] =
|
||||||
userAccountRepository.findByUsername(req.username) match
|
userAccountRepository.findByUsername(req.username) match
|
||||||
case None =>
|
case None =>
|
||||||
log.warnf("Login failed for unknown user %s", req.username)
|
log.warnf("Login failed for unknown user %s", req.username)
|
||||||
@@ -93,39 +89,16 @@ class AccountService:
|
|||||||
Left(AccountError.UserBanned)
|
Left(AccountError.UserBanned)
|
||||||
else
|
else
|
||||||
log.infof("User %s logged in successfully", req.username)
|
log.infof("User %s logged in successfully", req.username)
|
||||||
Right((generateAccessToken(account), generateRefreshToken(account.id)))
|
Right(
|
||||||
|
Jwt
|
||||||
def refresh(refreshToken: String): Either[AccountError, (String, String)] =
|
.issuer("nowchess")
|
||||||
try
|
.subject(account.id.toString)
|
||||||
val parsed = jwtParser.parse(refreshToken)
|
.claim("username", account.username)
|
||||||
if parsed.getClaim[String]("type") != "refresh" then Left(AccountError.InvalidRefreshToken)
|
.sign(),
|
||||||
else
|
)
|
||||||
val userId = UUID.fromString(parsed.getSubject)
|
|
||||||
userAccountRepository.findById(userId) match
|
|
||||||
case None => Left(AccountError.UserNotFound)
|
|
||||||
case Some(u) if u.banned => Left(AccountError.UserBanned)
|
|
||||||
case Some(u) => Right((generateAccessToken(u), generateRefreshToken(u.id)))
|
|
||||||
catch case _: Throwable => Left(AccountError.InvalidRefreshToken)
|
|
||||||
|
|
||||||
private def generateAccessToken(account: UserAccount): String =
|
|
||||||
Jwt
|
|
||||||
.issuer("nowchess")
|
|
||||||
.subject(account.id.toString)
|
|
||||||
.claim("username", account.username)
|
|
||||||
.expiresIn(3600)
|
|
||||||
.sign()
|
|
||||||
|
|
||||||
private def generateRefreshToken(userId: UUID): String =
|
|
||||||
Jwt
|
|
||||||
.issuer("nowchess")
|
|
||||||
.subject(userId.toString)
|
|
||||||
.claim("type", "refresh")
|
|
||||||
.expiresIn(30L * 24 * 3600)
|
|
||||||
.sign()
|
|
||||||
|
|
||||||
private def loginFailureReason(error: AccountError): String = error match
|
private def loginFailureReason(error: AccountError): String = error match
|
||||||
case AccountError.InvalidCredentials => "invalid_credentials"
|
case AccountError.InvalidCredentials => "invalid_credentials"
|
||||||
case AccountError.InvalidRefreshToken => "invalid_refresh_token"
|
|
||||||
case AccountError.UserBanned => "user_banned"
|
case AccountError.UserBanned => "user_banned"
|
||||||
case AccountError.UsernameTaken(_) => "username_taken"
|
case AccountError.UsernameTaken(_) => "username_taken"
|
||||||
case AccountError.EmailAlreadyRegistered(_) => "email_registered"
|
case AccountError.EmailAlreadyRegistered(_) => "email_registered"
|
||||||
|
|||||||
@@ -88,14 +88,14 @@ class ChallengeService:
|
|||||||
challenge.destUser = destUser
|
challenge.destUser = destUser
|
||||||
challenge.color = color
|
challenge.color = color
|
||||||
challenge.status = ChallengeStatus.Created
|
challenge.status = ChallengeStatus.Created
|
||||||
challenge.limitSeconds = req.timeControl.limitSeconds.map(java.lang.Integer.valueOf).orNull
|
challenge.timeControlType = req.timeControl.`type`
|
||||||
challenge.incrementSeconds = req.timeControl.incrementSeconds.map(java.lang.Integer.valueOf).orNull
|
challenge.timeControlLimit = req.timeControl.limit.map(java.lang.Integer.valueOf).orNull
|
||||||
challenge.daysPerMove = req.timeControl.daysPerMove.map(java.lang.Integer.valueOf).orNull
|
challenge.timeControlIncrement = req.timeControl.increment.map(java.lang.Integer.valueOf).orNull
|
||||||
challenge.createdAt = Instant.now()
|
challenge.createdAt = Instant.now()
|
||||||
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.errorf(ex, "Failed to notify dest user for challenge %s", challenge.id)
|
catch case ex: Exception => log.warnf(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.errorf(ex, "Failed to notify challenger for game %s", gameId)
|
catch case ex: Exception => log.warnf(ex, "Failed to notify challenger for game %s", gameId)
|
||||||
challenge
|
challenge
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -200,9 +200,10 @@ class ChallengeService:
|
|||||||
if ThreadLocalRandom.current().nextBoolean() then (challenger, destUser) else (destUser, challenger)
|
if ThreadLocalRandom.current().nextBoolean() then (challenger, destUser) else (destUser, challenger)
|
||||||
|
|
||||||
private def buildTimeControl(challenge: Challenge): Option[CoreTimeControl] =
|
private def buildTimeControl(challenge: Challenge): Option[CoreTimeControl] =
|
||||||
if challenge.limitSecondsOpt.isEmpty && challenge.incrementSecondsOpt.isEmpty && challenge.daysPerMoveOpt.isEmpty
|
challenge.timeControlType match
|
||||||
then None
|
case "unlimited" => None
|
||||||
else Some(CoreTimeControl(challenge.limitSecondsOpt, challenge.incrementSecondsOpt, challenge.daysPerMoveOpt))
|
case "correspondence" => Some(CoreTimeControl(None, None, challenge.timeControlLimitOpt))
|
||||||
|
case _ => Some(CoreTimeControl(challenge.timeControlLimitOpt, challenge.timeControlIncrementOpt, None))
|
||||||
|
|
||||||
private def parseColor(raw: String): Either[ChallengeError, ChallengeColor] =
|
private def parseColor(raw: String): Either[ChallengeError, ChallengeColor] =
|
||||||
raw.toLowerCase match
|
raw.toLowerCase match
|
||||||
@@ -226,7 +227,7 @@ class ChallengeService:
|
|||||||
destUser = PlayerInfo(c.destUser.id.toString, c.destUser.username, c.destUser.rating),
|
destUser = PlayerInfo(c.destUser.id.toString, c.destUser.username, c.destUser.rating),
|
||||||
variant = "standard",
|
variant = "standard",
|
||||||
color = c.color.toString.toLowerCase,
|
color = c.color.toString.toLowerCase,
|
||||||
timeControl = TimeControlDto(c.limitSecondsOpt, c.incrementSecondsOpt, c.daysPerMoveOpt),
|
timeControl = TimeControlDto(c.timeControlType, c.timeControlLimitOpt, c.timeControlIncrementOpt),
|
||||||
status = c.status.toString.toLowerCase,
|
status = c.status.toString.toLowerCase,
|
||||||
declineReason = c.declineReasonOpt.map(_.toString.toLowerCase),
|
declineReason = c.declineReasonOpt.map(_.toString.toLowerCase),
|
||||||
gameId = c.gameIdOpt,
|
gameId = c.gameIdOpt,
|
||||||
|
|||||||
+3
-52
@@ -32,24 +32,7 @@ class AccountResourceTest:
|
|||||||
.`then`()
|
.`then`()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract()
|
.extract()
|
||||||
.path[String]("accessToken")
|
.path[String]("token")
|
||||||
|
|
||||||
private def registerAndLoginPair(username: String): (String, String) =
|
|
||||||
givenRequest()
|
|
||||||
.body(registerBody(username))
|
|
||||||
.when()
|
|
||||||
.post("/api/account")
|
|
||||||
.`then`()
|
|
||||||
.statusCode(200)
|
|
||||||
val resp = givenRequest()
|
|
||||||
.body(loginBody(username))
|
|
||||||
.when()
|
|
||||||
.post("/api/account/login")
|
|
||||||
.`then`()
|
|
||||||
.statusCode(200)
|
|
||||||
.extract()
|
|
||||||
.response()
|
|
||||||
(resp.path[String]("accessToken"), resp.path[String]("refreshToken"))
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def registerReturns200(): Unit =
|
def registerReturns200(): Unit =
|
||||||
@@ -74,7 +57,7 @@ class AccountResourceTest:
|
|||||||
.body("error", containsString("bob"))
|
.body("error", containsString("bob"))
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def loginReturns200WithTokenPair(): Unit =
|
def loginReturns200WithToken(): Unit =
|
||||||
givenRequest().body(registerBody("charlie")).when().post("/api/account")
|
givenRequest().body(registerBody("charlie")).when().post("/api/account")
|
||||||
givenRequest()
|
givenRequest()
|
||||||
.body(loginBody("charlie"))
|
.body(loginBody("charlie"))
|
||||||
@@ -82,8 +65,7 @@ class AccountResourceTest:
|
|||||||
.post("/api/account/login")
|
.post("/api/account/login")
|
||||||
.`then`()
|
.`then`()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.body("accessToken", notNullValue())
|
.body("token", notNullValue())
|
||||||
.body("refreshToken", notNullValue())
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
def loginUnauthorizedOnWrongPassword(): Unit =
|
def loginUnauthorizedOnWrongPassword(): Unit =
|
||||||
@@ -123,34 +105,3 @@ class AccountResourceTest:
|
|||||||
.get("/api/account/doesnotexist")
|
.get("/api/account/doesnotexist")
|
||||||
.`then`()
|
.`then`()
|
||||||
.statusCode(404)
|
.statusCode(404)
|
||||||
|
|
||||||
@Test
|
|
||||||
def refreshReturnsNewTokenPair(): Unit =
|
|
||||||
val (_, refreshToken) = registerAndLoginPair("refresh_user")
|
|
||||||
givenRequest()
|
|
||||||
.body(s"""{"refreshToken":"$refreshToken"}""")
|
|
||||||
.when()
|
|
||||||
.post("/api/account/refresh")
|
|
||||||
.`then`()
|
|
||||||
.statusCode(200)
|
|
||||||
.body("accessToken", notNullValue())
|
|
||||||
.body("refreshToken", notNullValue())
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def refreshWithInvalidTokenReturns401(): Unit =
|
|
||||||
givenRequest()
|
|
||||||
.body("""{"refreshToken":"invalid.token.value"}""")
|
|
||||||
.when()
|
|
||||||
.post("/api/account/refresh")
|
|
||||||
.`then`()
|
|
||||||
.statusCode(401)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def refreshWithAccessTokenReturns401(): Unit =
|
|
||||||
val accessToken = registerAndLogin("refresh_bad_type")
|
|
||||||
givenRequest()
|
|
||||||
.body(s"""{"refreshToken":"$accessToken"}""")
|
|
||||||
.when()
|
|
||||||
.post("/api/account/refresh")
|
|
||||||
.`then`()
|
|
||||||
.statusCode(401)
|
|
||||||
|
|||||||
+2
-2
@@ -41,10 +41,10 @@ class ChallengeResourceTest:
|
|||||||
.`then`()
|
.`then`()
|
||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.extract()
|
.extract()
|
||||||
.path[String]("accessToken")
|
.path[String]("token")
|
||||||
|
|
||||||
private val clockBody =
|
private val clockBody =
|
||||||
"""{"color":"random","timeControl":{"limitSeconds":300,"incrementSeconds":5}}"""
|
"""{"color":"random","timeControl":{"type":"clock","limit":300,"increment":5}}"""
|
||||||
|
|
||||||
private def authed(token: String) =
|
private def authed(token: String) =
|
||||||
givenRequest().header("Authorization", s"Bearer $token")
|
givenRequest().header("Authorization", s"Bearer $token")
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=18
|
MINOR=14
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -109,21 +109,3 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
## (2026-05-22)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **dto:** update GameWritebackEventDto for JSON deserialization and remove unused mixin ([576e3fe](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/576e3fea9bf1082549ea53efd3288474c42be93d))
|
|
||||||
* 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-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-41 Bot Platform ([#33](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/33)) ([8744bee](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/8744bee2dd20966dae90a09c21a43d5b06f59e00))
|
|
||||||
* **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))
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **dependencies:** correct Jackson databind dependency group ID ([008d72d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/008d72d826707c04205bac7de25170fae5fed861))
|
|
||||||
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ dependencies {
|
|||||||
strictly(versions["SCALA_LIBRARY"]!!)
|
strictly(versions["SCALA_LIBRARY"]!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:${versions["JACKSON"]!!}")
|
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package de.nowchess.api.dto
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
|
||||||
|
|
||||||
case class GameWritebackEventDto(
|
case class GameWritebackEventDto(
|
||||||
gameId: String,
|
gameId: String,
|
||||||
fen: String,
|
fen: String,
|
||||||
@@ -16,11 +14,11 @@ case class GameWritebackEventDto(
|
|||||||
limitSeconds: Option[Int],
|
limitSeconds: Option[Int],
|
||||||
incrementSeconds: Option[Int],
|
incrementSeconds: Option[Int],
|
||||||
daysPerMove: Option[Int],
|
daysPerMove: Option[Int],
|
||||||
@JsonDeserialize(contentAs = classOf[java.lang.Long]) whiteRemainingMs: Option[Long],
|
whiteRemainingMs: Option[Long],
|
||||||
@JsonDeserialize(contentAs = classOf[java.lang.Long]) blackRemainingMs: Option[Long],
|
blackRemainingMs: Option[Long],
|
||||||
@JsonDeserialize(contentAs = classOf[java.lang.Long]) incrementMs: Option[Long],
|
incrementMs: Option[Long],
|
||||||
@JsonDeserialize(contentAs = classOf[java.lang.Long]) clockLastTickAt: Option[Long],
|
clockLastTickAt: Option[Long],
|
||||||
@JsonDeserialize(contentAs = classOf[java.lang.Long]) clockMoveDeadline: Option[Long],
|
clockMoveDeadline: Option[Long],
|
||||||
clockActiveColor: Option[String],
|
clockActiveColor: Option[String],
|
||||||
pendingDrawOffer: Option[String],
|
pendingDrawOffer: Option[String],
|
||||||
result: Option[String] = None,
|
result: Option[String] = None,
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=13
|
MINOR=12
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -334,648 +334,3 @@
|
|||||||
* **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))
|
|
||||||
## (2026-05-16)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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-17)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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))
|
|
||||||
* remove unused clearDrainingByPodName method and update HealthMonitor to clear draining instances ([1a02f9e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1a02f9e18673d0038e9a307fee5ea5219dc76af8))
|
|
||||||
* 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-17)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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))
|
|
||||||
* refresh Redis TTL on instance heartbeat to prevent false DEAD marking ([2d76c00](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2d76c001fe22868190a546f1794cf0ade36bb9a9))
|
|
||||||
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
|
||||||
* remove redundant line break in LoadBalancer.scala for improved readability ([5205468](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/520546853447e0e0992b258c264272f8f7b8b438))
|
|
||||||
* remove unused clearDrainingByPodName method and update HealthMonitor to clear draining instances ([1a02f9e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1a02f9e18673d0038e9a307fee5ea5219dc76af8))
|
|
||||||
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* 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-17)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* correct pod matching logic from endsWith to contains ([6dbe1e6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6dbe1e62ac74f4ddbf03049b20184f7fac793f81))
|
|
||||||
* **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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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))
|
|
||||||
* refresh Redis TTL on instance heartbeat to prevent false DEAD marking ([2d76c00](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2d76c001fe22868190a546f1794cf0ade36bb9a9))
|
|
||||||
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
|
||||||
* remove redundant line break in LoadBalancer.scala for improved readability ([5205468](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/520546853447e0e0992b258c264272f8f7b8b438))
|
|
||||||
* remove unused clearDrainingByPodName method and update HealthMonitor to clear draining instances ([1a02f9e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1a02f9e18673d0038e9a307fee5ea5219dc76af8))
|
|
||||||
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* 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-17)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* correct pod matching logic from endsWith to contains ([6dbe1e6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6dbe1e62ac74f4ddbf03049b20184f7fac793f81))
|
|
||||||
* **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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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))
|
|
||||||
* refresh Redis TTL on instance heartbeat to prevent false DEAD marking ([2d76c00](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2d76c001fe22868190a546f1794cf0ade36bb9a9))
|
|
||||||
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
|
||||||
* remove redundant line break in LoadBalancer.scala for improved readability ([5205468](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/520546853447e0e0992b258c264272f8f7b8b438))
|
|
||||||
* remove unused clearDrainingByPodName method and update HealthMonitor to clear draining instances ([1a02f9e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1a02f9e18673d0038e9a307fee5ea5219dc76af8))
|
|
||||||
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* revert pod matching to original logic instanceId.contains(podName) ([9bf995f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9bf995f47d4dec19dd62ce2f7d52286ec2aa575f))
|
|
||||||
* 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-18)
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add configurable CPU and memory scaling thresholds for auto-scaling ([a07bf89](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a07bf89fae43e3ef5fdd30aed0429742a95f8bbe))
|
|
||||||
* 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))
|
|
||||||
* force delete pod immediately on heartbeat loss ([a9f4606](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a9f4606b40fcaf9ec59fc2503a40054264bcbccf))
|
|
||||||
* 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))
|
|
||||||
* correct pod matching logic from endsWith to contains ([6dbe1e6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/6dbe1e62ac74f4ddbf03049b20184f7fac793f81))
|
|
||||||
* **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))
|
|
||||||
* improve pod instance ID matching logic in AutoScaler and HealthMonitor ([f109fe3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f109fe3860371dd0be3434b10a721936dc258b16))
|
|
||||||
* 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))
|
|
||||||
* refresh Redis TTL on instance heartbeat to prevent false DEAD marking ([2d76c00](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2d76c001fe22868190a546f1794cf0ade36bb9a9))
|
|
||||||
* remove corrupted instances immediately and evict dead instances ([43184d2](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/43184d296da5a6a7b760ac90c2b739220d86bce3))
|
|
||||||
* remove redundant line break in LoadBalancer.scala for improved readability ([5205468](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/520546853447e0e0992b258c264272f8f7b8b438))
|
|
||||||
* remove unused clearDrainingByPodName method and update HealthMonitor to clear draining instances ([1a02f9e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1a02f9e18673d0038e9a307fee5ea5219dc76af8))
|
|
||||||
* replace null checks with Option in coordinator ([2b04d7f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2b04d7fa713e06662bff5afe3fb3f9d04541ce51))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* revert pod matching to original logic instanceId.contains(podName) ([9bf995f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/9bf995f47d4dec19dd62ce2f7d52286ec2aa575f))
|
|
||||||
* 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,7 +78,6 @@ 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: 100
|
max-games-per-core: 500
|
||||||
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: true
|
auto-scale-enabled: false
|
||||||
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,8 +47,6 @@ 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,9 +62,3 @@ 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
|
|
||||||
|
|||||||
+1
-2
@@ -127,8 +127,7 @@ 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)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
||||||
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)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
||||||
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)).withDeadlineAfter(5, TimeUnit.SECONDS)
|
val stub = CoordinatorServiceGrpc.newBlockingStub(getChannel(host, port))
|
||||||
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)
|
||||||
|
|||||||
+83
-233
@@ -8,13 +8,9 @@ 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
|
||||||
@@ -29,34 +25,20 @@ 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)
|
|
||||||
|
|
||||||
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 =
|
||||||
@@ -69,11 +51,6 @@ 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[?, ?] =>
|
||||||
@@ -81,91 +58,6 @@ 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(pod => instanceId.contains(pod.getMetadata.getName)).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()
|
||||||
@@ -173,136 +65,94 @@ 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)
|
||||||
|
|
||||||
val constrainedInstance = instances.find(inst => isResourceConstrained(inst.instanceId))
|
if avgLoad > config.scaleUpThreshold * config.maxGamesPerCore then scaleUp()
|
||||||
val hasHighCpuOrMemory = constrainedInstance.isDefined
|
else if avgLoad < config.scaleDownThreshold * config.maxGamesPerCore then scaleDown()
|
||||||
|
|
||||||
log.infof(
|
|
||||||
"Scale check: instances=%d avgLoad=%.1f resourceConstrained=%s",
|
|
||||||
instances.size,
|
|
||||||
avgLoad,
|
|
||||||
constrainedInstance.map(_.instanceId).getOrElse("none"),
|
|
||||||
)
|
|
||||||
|
|
||||||
if hasHighCpuOrMemory then scaleUp()
|
|
||||||
if !hasHighCpuOrMemory && 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 => log.warn("Kubernetes client not available, cannot scale")
|
case None =>
|
||||||
|
log.warn("Kubernetes client not available, cannot scale")
|
||||||
case Some(kube) =>
|
case Some(kube) =>
|
||||||
patchRolloutReplicas(
|
try
|
||||||
kube,
|
Option(
|
||||||
direction = "up",
|
kube
|
||||||
delta = 1,
|
.genericKubernetesResources(argoApiVersion, argoKind)
|
||||||
canScale = _ < config.scaleMaxReplicas,
|
.inNamespace(config.k8sNamespace)
|
||||||
atLimit = n => log.infof("Already at max replicas %d for %s", n, config.k8sRolloutName),
|
.withName(config.k8sRolloutName)
|
||||||
onSuccess = (from, to) =>
|
.get(),
|
||||||
log.infof("Scaled up %s from %d to %d replicas", config.k8sRolloutName, from, to)
|
).foreach { rollout =>
|
||||||
loadBalancer.rebalance,
|
rolloutSpec(rollout).foreach { spec =>
|
||||||
)
|
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")
|
||||||
val underloadedInstance = instanceRegistry.getAllInstances
|
|
||||||
.filter(_.state == "HEALTHY")
|
|
||||||
.minByOption(_.subscriptionCount)
|
|
||||||
|
|
||||||
underloadedInstance.foreach { inst =>
|
|
||||||
log.infof("Marking instance %s for drain before scale-down", inst.instanceId)
|
|
||||||
drainingForScaleDown.add(inst.instanceId)
|
|
||||||
failoverService
|
|
||||||
.onInstanceStreamDropped(inst.instanceId)
|
|
||||||
.subscribe()
|
|
||||||
.`with`(
|
|
||||||
_ => log.debugf("Instance %s drained for scale-down", inst.instanceId),
|
|
||||||
ex => log.warnf(ex, "Drain failed for %s, proceeding with scale-down", inst.instanceId),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeClientOpt match
|
kubeClientOpt match
|
||||||
case None => log.warn("Kubernetes client not available, cannot scale")
|
case None =>
|
||||||
|
log.warn("Kubernetes client not available, cannot scale")
|
||||||
case Some(kube) =>
|
case Some(kube) =>
|
||||||
patchRolloutReplicas(
|
try
|
||||||
kube,
|
Option(
|
||||||
direction = "down",
|
kube
|
||||||
delta = -1,
|
.genericKubernetesResources(argoApiVersion, argoKind)
|
||||||
canScale = _ > config.scaleMinReplicas,
|
.inNamespace(config.k8sNamespace)
|
||||||
atLimit = n => log.infof("Already at min replicas %d for %s", n, config.k8sRolloutName),
|
.withName(config.k8sRolloutName)
|
||||||
onSuccess = (from, to) =>
|
.get(),
|
||||||
log.infof("Scaled down %s from %d to %d replicas", config.k8sRolloutName, from, to)
|
).foreach { rollout =>
|
||||||
underloadedInstance.foreach(inst => forceDeletePod(inst.instanceId, kube)),
|
rolloutSpec(rollout).foreach { spec =>
|
||||||
)
|
spec.get("replicas") match
|
||||||
|
case replicas: Integer =>
|
||||||
|
val currentReplicas = replicas.intValue()
|
||||||
|
val minReplicas = config.scaleMinReplicas
|
||||||
|
|
||||||
private def forceDeletePod(instanceId: String, kube: KubernetesClient): Unit =
|
if currentReplicas > minReplicas then
|
||||||
try
|
spec.put("replicas", Integer.valueOf(currentReplicas - 1))
|
||||||
val pods = kube
|
kube
|
||||||
.pods()
|
.genericKubernetesResources(argoApiVersion, argoKind)
|
||||||
.inNamespace(config.k8sNamespace)
|
.inNamespace(config.k8sNamespace)
|
||||||
.withLabel(config.k8sRolloutLabelSelector)
|
.resource(rollout)
|
||||||
.list()
|
.update()
|
||||||
.getItems
|
meterRegistry.counter("nowchess.coordinator.scale.events", "direction", "down").increment()
|
||||||
.asScala
|
log.infof(
|
||||||
pods.find(pod => instanceId.contains(pod.getMetadata.getName)) match
|
"Scaled down %s from %d to %d replicas",
|
||||||
case Some(pod) =>
|
config.k8sRolloutName,
|
||||||
kube.pods().inNamespace(config.k8sNamespace).withName(pod.getMetadata.getName).withGracePeriod(0L).delete()
|
currentReplicas,
|
||||||
log.infof("Force-deleted pod for drained instance %s", instanceId)
|
currentReplicas - 1,
|
||||||
case None =>
|
)
|
||||||
log.debugf("No pod found for drained instance %s, skipping deletion", instanceId)
|
else log.infof("Already at min replicas %d for %s", minReplicas, config.k8sRolloutName)
|
||||||
catch
|
case _ => ()
|
||||||
case ex: Exception =>
|
}
|
||||||
log.warnf(ex, "Failed to force-delete pod for drained instance %s", instanceId)
|
}
|
||||||
|
catch
|
||||||
|
case ex: Exception =>
|
||||||
|
meterRegistry.counter("nowchess.coordinator.scale.failures", "direction", "down").increment()
|
||||||
|
log.warnf(ex, "Failed to scale down %s", config.k8sRolloutName)
|
||||||
|
|||||||
+9
-17
@@ -7,7 +7,6 @@ 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
|
||||||
@@ -49,11 +48,6 @@ 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)
|
||||||
|
|
||||||
@@ -75,20 +69,19 @@ class CacheEvictionManager:
|
|||||||
try
|
try
|
||||||
coreGrpcClient.evictGames(instance.hostname, instance.grpcPort, List(gameId))
|
coreGrpcClient.evictGames(instance.hostname, instance.grpcPort, List(gameId))
|
||||||
redis.key(classOf[String]).del(key)
|
redis.key(classOf[String]).del(key)
|
||||||
redis.key(classOf[String]).del(s"$redisPrefix:game:$gameId:instance")
|
|
||||||
meterRegistry.counter("nowchess.coordinator.cache.evictions").increment()
|
meterRegistry.counter("nowchess.coordinator.cache.evictions").increment()
|
||||||
log.infof("Evicted idle game %s from %s", gameId, instance.instanceId)
|
log.infof("Evicted idle game %s from %s", gameId, instance.instanceId)
|
||||||
count + 1
|
count + 1
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.errorf(ex, "Failed to evict game %s", gameId)
|
log.warnf(ex, "Failed to evict game %s", gameId)
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
else count
|
else count
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.errorf(ex, "Error processing game key %s", key)
|
log.warnf(ex, "Error processing game key %s", key)
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,18 +90,17 @@ class CacheEvictionManager:
|
|||||||
private def extractLastUpdatedTimestamp(json: String): Long =
|
private def extractLastUpdatedTimestamp(json: String): Long =
|
||||||
Try {
|
Try {
|
||||||
val parsed = objectMapper.readTree(json)
|
val parsed = objectMapper.readTree(json)
|
||||||
Option(parsed.get("lastUpdatedMs"))
|
Option(parsed.get("lastHeartbeat"))
|
||||||
.filter(_.isNumber)
|
.filter(_.isTextual)
|
||||||
.fold(0L)(_.asLong())
|
.fold(0L)(lh => Instant.parse(lh.asText()).toEpochMilli)
|
||||||
}.getOrElse(0L)
|
}.getOrElse(0L)
|
||||||
|
|
||||||
private def findInstanceWithGame(gameId: String): Option[de.nowchess.coordinator.dto.InstanceMetadata] =
|
private def findInstanceWithGame(gameId: String): Option[de.nowchess.coordinator.dto.InstanceMetadata] =
|
||||||
try
|
try
|
||||||
val mapKey = s"$redisPrefix:game:$gameId:instance"
|
instanceRegistry.getAllInstances.find { instance =>
|
||||||
Option(redis.value(classOf[String]).get(mapKey))
|
val setKey = s"$redisPrefix:instance:${instance.instanceId}:games"
|
||||||
.flatMap { instanceId =>
|
redis.set(classOf[String]).sismember(setKey, gameId)
|
||||||
instanceRegistry.getInstance(instanceId)
|
}
|
||||||
}
|
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.debugf(ex, "Failed to find instance for game %s", gameId)
|
log.debugf(ex, "Failed to find instance for game %s", gameId)
|
||||||
|
|||||||
+8
-59
@@ -1,7 +1,6 @@
|
|||||||
package de.nowchess.coordinator.service
|
package de.nowchess.coordinator.service
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
import jakarta.enterprise.inject.Instance
|
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
@@ -10,7 +9,6 @@ import org.jboss.logging.Logger
|
|||||||
import de.nowchess.coordinator.dto.InstanceMetadata
|
import de.nowchess.coordinator.dto.InstanceMetadata
|
||||||
import de.nowchess.coordinator.grpc.CoreGrpcClient
|
import de.nowchess.coordinator.grpc.CoreGrpcClient
|
||||||
import de.nowchess.coordinator.config.CoordinatorConfig
|
import de.nowchess.coordinator.config.CoordinatorConfig
|
||||||
import io.fabric8.kubernetes.client.KubernetesClient
|
|
||||||
import io.smallrye.mutiny.Uni
|
import io.smallrye.mutiny.Uni
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
@@ -29,17 +27,10 @@ class FailoverService:
|
|||||||
@Inject
|
@Inject
|
||||||
private var config: CoordinatorConfig = uninitialized
|
private var config: CoordinatorConfig = uninitialized
|
||||||
|
|
||||||
@Inject
|
|
||||||
private var kubeClientInstance: Instance[KubernetesClient] = uninitialized
|
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[FailoverService])
|
private val log = Logger.getLogger(classOf[FailoverService])
|
||||||
private var redisPrefix = "nowchess"
|
private var redisPrefix = "nowchess"
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
private def kubeClientOpt: Option[KubernetesClient] =
|
|
||||||
if kubeClientInstance.isUnsatisfied then None
|
|
||||||
else Some(kubeClientInstance.get())
|
|
||||||
|
|
||||||
def setRedisPrefix(prefix: String): Unit =
|
def setRedisPrefix(prefix: String): Unit =
|
||||||
redisPrefix = prefix
|
redisPrefix = prefix
|
||||||
|
|
||||||
@@ -48,7 +39,6 @@ class FailoverService:
|
|||||||
|
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
instanceRegistry.markInstanceDead(instanceId)
|
instanceRegistry.markInstanceDead(instanceId)
|
||||||
deleteK8sPod(instanceId)
|
|
||||||
|
|
||||||
val gameIds = getOrphanedGames(instanceId)
|
val gameIds = getOrphanedGames(instanceId)
|
||||||
log.infof("Found %d orphaned games for instance %s", gameIds.size, instanceId)
|
log.infof("Found %d orphaned games for instance %s", gameIds.size, instanceId)
|
||||||
@@ -117,70 +107,29 @@ class FailoverService:
|
|||||||
try
|
try
|
||||||
val subscribed = coreGrpcClient.batchResubscribeGames(target.hostname, target.grpcPort, batch)
|
val subscribed = coreGrpcClient.batchResubscribeGames(target.hostname, target.grpcPort, batch)
|
||||||
if subscribed > 0 then
|
if subscribed > 0 then
|
||||||
updateGameInstanceMappings(batch, deadId, target.instanceId)
|
|
||||||
log.infof("Migrated %d games from %s to %s", subscribed, deadId, target.instanceId)
|
log.infof("Migrated %d games from %s to %s", subscribed, deadId, target.instanceId)
|
||||||
true
|
true
|
||||||
else false
|
else false
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.errorf(ex, "Failed to migrate batch to %s, trying next", target.instanceId)
|
log.warnf(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)
|
||||||
|
|
||||||
private def updateGameInstanceMappings(gameIds: List[String], deadId: String, targetId: String): Unit =
|
|
||||||
try
|
|
||||||
val fromKey = s"$redisPrefix:instance:$deadId:games"
|
|
||||||
val toKey = s"$redisPrefix:instance:$targetId:games"
|
|
||||||
gameIds.foreach { gameId =>
|
|
||||||
redis.set(classOf[String]).sadd(toKey, gameId)
|
|
||||||
redis.value(classOf[String]).set(s"$redisPrefix:game:$gameId:instance", targetId)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
case ex: Exception =>
|
|
||||||
log.errorf(ex, "Failed to update game instance mappings")
|
|
||||||
|
|
||||||
private def deleteK8sPod(instanceId: String): Unit =
|
|
||||||
kubeClientOpt match
|
|
||||||
case None =>
|
|
||||||
log.debugf("Kubernetes client not available, skipping pod deletion for %s", instanceId)
|
|
||||||
case Some(kube) =>
|
|
||||||
try
|
|
||||||
val pods = kube
|
|
||||||
.pods()
|
|
||||||
.inNamespace(config.k8sNamespace)
|
|
||||||
.withLabel(config.k8sRolloutLabelSelector)
|
|
||||||
.list()
|
|
||||||
.getItems
|
|
||||||
.asScala
|
|
||||||
|
|
||||||
pods.find(pod => instanceId.contains(pod.getMetadata.getName)) match
|
|
||||||
case Some(pod) =>
|
|
||||||
val podName = pod.getMetadata.getName
|
|
||||||
kube.pods().inNamespace(config.k8sNamespace).withName(podName).withGracePeriod(0L).delete()
|
|
||||||
log.infof("Force-deleted pod %s for dead instance %s", podName, instanceId)
|
|
||||||
case None =>
|
|
||||||
log.debugf("No pod found for instance %s, skipping deletion", instanceId)
|
|
||||||
catch
|
|
||||||
case ex: Exception =>
|
|
||||||
log.errorf(ex, "Failed to delete pod for instance %s", instanceId)
|
|
||||||
|
|
||||||
private def cleanupDeadInstance(instanceId: String): Unit =
|
private def cleanupDeadInstance(instanceId: String): Unit =
|
||||||
val setKey = s"$redisPrefix:instance:$instanceId:games"
|
val setKey = s"$redisPrefix:instance:$instanceId:games"
|
||||||
redis.key(classOf[String]).del(setKey)
|
redis.key(classOf[String]).del(setKey)
|
||||||
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
|
Uni.createFrom().deferred(() =>
|
||||||
.createFrom()
|
instanceRegistry.getAllInstances
|
||||||
.deferred(() =>
|
.filter(_.state == "HEALTHY")
|
||||||
instanceRegistry.getAllInstances
|
.sortBy(_.subscriptionCount)
|
||||||
.filter(_.state == "HEALTHY")
|
.headOption match
|
||||||
.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)
|
||||||
|
|||||||
+30
-49
@@ -5,7 +5,6 @@ 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
|
||||||
@@ -40,14 +39,11 @@ class HealthMonitor:
|
|||||||
private var meterRegistry: MeterRegistry = uninitialized
|
private var meterRegistry: MeterRegistry = uninitialized
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private var grpcServerInstance: Instance[CoordinatorGrpcServer] = uninitialized
|
private var grpcServer: 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
|
||||||
@@ -56,10 +52,6 @@ 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
|
||||||
|
|
||||||
@@ -77,28 +69,20 @@ class HealthMonitor:
|
|||||||
Thread.ofVirtual().start(() => validateStartupInstances(timeoutMs))
|
Thread.ofVirtual().start(() => validateStartupInstances(timeoutMs))
|
||||||
startPodWatch()
|
startPodWatch()
|
||||||
|
|
||||||
@Scheduled(every = "10s")
|
def checkInstanceHealth: Unit =
|
||||||
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)
|
||||||
evicted.foreach(autoScaler.clearDraining)
|
|
||||||
val instances = instanceRegistry.getAllInstances
|
val instances = instanceRegistry.getAllInstances
|
||||||
val failed = instances.collect { inst =>
|
instances.foreach { 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
|
|
||||||
|
|
||||||
private def checkHealth(instanceId: String): Boolean =
|
private def checkHealth(instanceId: String): Boolean =
|
||||||
val redisHealthy = checkRedisHeartbeat(instanceId)
|
val redisHealthy = checkRedisHeartbeat(instanceId)
|
||||||
@@ -127,7 +111,7 @@ class HealthMonitor:
|
|||||||
|
|
||||||
pods.exists { pod =>
|
pods.exists { pod =>
|
||||||
val podName = pod.getMetadata.getName
|
val podName = pod.getMetadata.getName
|
||||||
instanceId.contains(podName) && isPodReady(pod)
|
podName.contains(instanceId) && isPodReady(pod)
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
@@ -149,18 +133,19 @@ class HealthMonitor:
|
|||||||
action match
|
action match
|
||||||
case Watcher.Action.DELETED =>
|
case Watcher.Action.DELETED =>
|
||||||
handlePodGone(pod)
|
handlePodGone(pod)
|
||||||
case Watcher.Action.MODIFIED if Option(pod.getMetadata.getDeletionTimestamp).isDefined =>
|
case Watcher.Action.MODIFIED
|
||||||
|
if Option(pod.getMetadata.getDeletionTimestamp).isDefined =>
|
||||||
handlePodTerminating(pod)
|
handlePodTerminating(pod)
|
||||||
case _ => ()
|
case _ => ()
|
||||||
|
|
||||||
override def onClose(cause: WatcherException): Unit =
|
override def onClose(cause: WatcherException): Unit =
|
||||||
Option(cause).foreach { ex =>
|
if cause != null then
|
||||||
log.warnf(ex, "Pod watch closed, restarting")
|
log.warnf(cause, "Pod watch closed, restarting")
|
||||||
startPodWatch()
|
startPodWatch()
|
||||||
},
|
|
||||||
)
|
)
|
||||||
log.info("Pod watch started")
|
log.info("Pod watch started")
|
||||||
catch case ex: Exception => log.warnf(ex, "Failed to start pod watch")
|
catch
|
||||||
|
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)
|
||||||
@@ -181,36 +166,29 @@ class HealthMonitor:
|
|||||||
.getItems
|
.getItems
|
||||||
.asScala
|
.asScala
|
||||||
|
|
||||||
pods.find(pod => instanceId.contains(pod.getMetadata.getName)) 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).withGracePeriod(0L).delete()
|
kube.pods().inNamespace(config.k8sNamespace).withName(podName).delete()
|
||||||
meterRegistry.counter("nowchess.coordinator.pods.deleted").increment()
|
meterRegistry.counter("nowchess.coordinator.pods.deleted").increment()
|
||||||
log.infof("Force-deleted pod %s for dead instance %s", podName, instanceId)
|
log.infof("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.errorf(
|
log.warnf(ex, "Failed to delete pod for instance %s", instanceId)
|
||||||
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)
|
||||||
grpcServerOpt.foreach { grpcServer =>
|
instanceRegistry.getAllInstances.foreach { inst =>
|
||||||
instanceRegistry.getAllInstances.foreach { inst =>
|
if !grpcServer.hasActiveStream(inst.instanceId) then
|
||||||
if !grpcServer.hasActiveStream(inst.instanceId) then
|
log.warnf(
|
||||||
log.warnf(
|
"Startup: instance %s did not reconnect within %dms — evicting",
|
||||||
"Startup: instance %s did not reconnect within %dms — evicting",
|
inst.instanceId,
|
||||||
inst.instanceId,
|
timeoutMs,
|
||||||
timeoutMs,
|
)
|
||||||
)
|
instanceRegistry.removeInstance(inst.instanceId)
|
||||||
instanceRegistry.removeInstance(inst.instanceId)
|
deleteK8sPod(inst.instanceId)
|
||||||
deleteK8sPod(inst.instanceId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def handlePodTerminating(pod: Pod): Unit =
|
private def handlePodTerminating(pod: Pod): Unit =
|
||||||
@@ -226,9 +204,12 @@ class HealthMonitor:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def handlePodGone(pod: Pod): Unit =
|
private def handlePodGone(pod: Pod): Unit =
|
||||||
val podName = pod.getMetadata.getName
|
|
||||||
findRegisteredInstance(pod).foreach { inst =>
|
findRegisteredInstance(pod).foreach { inst =>
|
||||||
log.warnf("Pod %s deleted — triggering failover for %s", podName, inst.instanceId)
|
log.warnf(
|
||||||
|
"Pod %s deleted — triggering failover for %s",
|
||||||
|
pod.getMetadata.getName,
|
||||||
|
inst.instanceId,
|
||||||
|
)
|
||||||
failoverService
|
failoverService
|
||||||
.onInstanceStreamDropped(inst.instanceId)
|
.onInstanceStreamDropped(inst.instanceId)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
@@ -240,4 +221,4 @@ class HealthMonitor:
|
|||||||
|
|
||||||
private def findRegisteredInstance(pod: Pod): Option[InstanceMetadata] =
|
private def findRegisteredInstance(pod: Pod): Option[InstanceMetadata] =
|
||||||
val podName = pod.getMetadata.getName
|
val podName = pod.getMetadata.getName
|
||||||
instanceRegistry.getAllInstances.find(inst => inst.instanceId.contains(podName))
|
instanceRegistry.getAllInstances.find(inst => podName.contains(inst.instanceId))
|
||||||
|
|||||||
+21
-45
@@ -9,7 +9,6 @@ import scala.jdk.CollectionConverters.*
|
|||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import de.nowchess.coordinator.dto.InstanceMetadata
|
import de.nowchess.coordinator.dto.InstanceMetadata
|
||||||
import de.nowchess.coordinator.config.CoordinatorConfig
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.time.{Duration, Instant}
|
import java.time.{Duration, Instant}
|
||||||
import io.micrometer.core.instrument.{Gauge, MeterRegistry}
|
import io.micrometer.core.instrument.{Gauge, MeterRegistry}
|
||||||
@@ -28,9 +27,6 @@ class InstanceRegistry:
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private var meterRegistry: MeterRegistry = uninitialized
|
private var meterRegistry: MeterRegistry = uninitialized
|
||||||
|
|
||||||
@Inject
|
|
||||||
private var config: CoordinatorConfig = uninitialized
|
|
||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[InstanceRegistry])
|
private val log = Logger.getLogger(classOf[InstanceRegistry])
|
||||||
@@ -55,15 +51,14 @@ 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)
|
||||||
Option(json).foreach { jsonStr =>
|
if json != null then
|
||||||
try
|
try
|
||||||
val metadata = mapper.readValue(jsonStr, classOf[InstanceMetadata])
|
val metadata = mapper.readValue(json, 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] =
|
||||||
@@ -80,38 +75,23 @@ class InstanceRegistry:
|
|||||||
.onItem()
|
.onItem()
|
||||||
.transformToUni { value =>
|
.transformToUni { value =>
|
||||||
try
|
try
|
||||||
Option(value).fold(
|
val metadata = mapper.readValue(value, classOf[InstanceMetadata])
|
||||||
{
|
val isNew = !instances.containsKey(instanceId)
|
||||||
log.debugf("Instance %s metadata missing from Redis (may have expired)", instanceId)
|
instances.put(instanceId, metadata)
|
||||||
Uni.createFrom().item(())
|
if isNew then
|
||||||
},
|
meterRegistry.counter("nowchess.coordinator.instances.joined").increment()
|
||||||
) { json =>
|
log.infof("Instance %s joined registry (subscriptions=%d)", instanceId, metadata.subscriptionCount)
|
||||||
val metadata = mapper.readValue(json, classOf[InstanceMetadata])
|
else
|
||||||
val isNew = !instances.containsKey(instanceId)
|
log.debugf(
|
||||||
instances.put(instanceId, metadata)
|
"Instance %s updated (subscriptions=%d state=%s)",
|
||||||
if isNew then
|
instanceId,
|
||||||
meterRegistry.counter("nowchess.coordinator.instances.joined").increment()
|
metadata.subscriptionCount,
|
||||||
log.infof("Instance %s joined registry (subscriptions=%d)", instanceId, metadata.subscriptionCount)
|
metadata.state,
|
||||||
else
|
)
|
||||||
log.debugf(
|
Uni.createFrom().item(())
|
||||||
"Instance %s updated (subscriptions=%d state=%s)",
|
|
||||||
instanceId,
|
|
||||||
metadata.subscriptionCount,
|
|
||||||
metadata.state,
|
|
||||||
)
|
|
||||||
val ttlMs = config.heartbeatTtl.toMillis
|
|
||||||
redis
|
|
||||||
.key(classOf[String])
|
|
||||||
.pexpire(key, ttlMs)
|
|
||||||
.map(_ => ())
|
|
||||||
.onFailure()
|
|
||||||
.recoverWithItem(())
|
|
||||||
}
|
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.errorf(ex, "Failed to parse instance metadata for %s — removing from registry", instanceId)
|
log.warnf(ex, "Failed to parse instance metadata for %s", instanceId)
|
||||||
instances.remove(instanceId)
|
|
||||||
meterRegistry.counter("nowchess.coordinator.instances.removed").increment()
|
|
||||||
Uni.createFrom().item(())
|
Uni.createFrom().item(())
|
||||||
}
|
}
|
||||||
.onFailure()
|
.onFailure()
|
||||||
@@ -131,19 +111,15 @@ class InstanceRegistry:
|
|||||||
val stale = instances.asScala
|
val stale = instances.asScala
|
||||||
.collect { case (id, inst) =>
|
.collect { case (id, inst) =>
|
||||||
try
|
try
|
||||||
val isHeartbeatStale = Instant.parse(inst.lastHeartbeat).isBefore(cutoff)
|
if Instant.parse(inst.lastHeartbeat).isBefore(cutoff) then Some(id)
|
||||||
val isDead = inst.state == "DEAD"
|
else None
|
||||||
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 =>
|
||||||
val inst = Option(instances.remove(id))
|
instances.remove(id)
|
||||||
meterRegistry.counter("nowchess.coordinator.instances.evicted").increment()
|
meterRegistry.counter("nowchess.coordinator.instances.evicted").increment()
|
||||||
inst.foreach { i =>
|
log.warnf("Evicted stale instance %s (heartbeat older than %s)", id, maxAge)
|
||||||
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
-15
@@ -4,7 +4,6 @@ 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.*
|
||||||
@@ -69,7 +68,7 @@ class LoadBalancer:
|
|||||||
|
|
||||||
val overloaded = instances
|
val overloaded = instances
|
||||||
.filter(_.subscriptionCount > config.maxGamesPerCore)
|
.filter(_.subscriptionCount > config.maxGamesPerCore)
|
||||||
.sortBy(_.subscriptionCount)
|
.sortBy[Int](_.subscriptionCount)
|
||||||
.reverse
|
.reverse
|
||||||
val underloaded = instances
|
val underloaded = instances
|
||||||
.filter(_.subscriptionCount < avgLoad * 0.8)
|
.filter(_.subscriptionCount < avgLoad * 0.8)
|
||||||
@@ -96,21 +95,19 @@ 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.errorf(ex, "Failed to move games from %s to %s", over.instanceId, target.instanceId)
|
log.warnf(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.errorf(ex, "Rebalance failed")
|
log.warnf(ex, "Rebalance failed")
|
||||||
|
|
||||||
private def getGamesToMove(instanceId: String, count: Int): List[String] =
|
private def getGamesToMove(instanceId: String, count: Int): List[String] =
|
||||||
try
|
try
|
||||||
val setKey = s"$redisPrefix:instance:$instanceId:games"
|
val setKey = s"$redisPrefix:instance:$instanceId:games"
|
||||||
val result = scala.collection.mutable.ListBuffer[String]()
|
redis.set(classOf[String]).smembers(setKey).asScala.toList.take(count)
|
||||||
for _ <- 0 until count do Option(redis.set(classOf[String]).spop(setKey)).foreach(result += _)
|
|
||||||
result.toList
|
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.debugf(ex, "Failed to get games for %s", instanceId)
|
log.debugf(ex, "Failed to get games for %s", instanceId)
|
||||||
@@ -118,16 +115,13 @@ class LoadBalancer:
|
|||||||
|
|
||||||
private def updateRedisGameSets(fromInstanceId: String, toInstanceId: String, gameIds: List[String]): Unit =
|
private def updateRedisGameSets(fromInstanceId: String, toInstanceId: String, gameIds: List[String]): Unit =
|
||||||
try
|
try
|
||||||
val toKey = s"$redisPrefix:instance:$toInstanceId:games"
|
val fromKey = s"$redisPrefix:instance:$fromInstanceId:games"
|
||||||
|
val toKey = s"$redisPrefix:instance:$toInstanceId:games"
|
||||||
|
|
||||||
gameIds.foreach { gameId =>
|
gameIds.foreach { gameId =>
|
||||||
|
redis.set(classOf[String]).srem(fromKey, gameId)
|
||||||
redis.set(classOf[String]).sadd(toKey, gameId)
|
redis.set(classOf[String]).sadd(toKey, gameId)
|
||||||
redis.value(classOf[String]).set(s"$redisPrefix:game:$gameId:instance", toInstanceId)
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
case ex: Exception =>
|
case ex: Exception =>
|
||||||
log.errorf(ex, "Failed to update Redis game sets")
|
log.warnf(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=32
|
MINOR=18
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -1195,500 +1195,3 @@
|
|||||||
|
|
||||||
* 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))
|
|
||||||
## (2026-05-17)
|
|
||||||
|
|
||||||
### 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))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* 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-18)
|
|
||||||
|
|
||||||
### 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))
|
|
||||||
* **core:** add logs to trace subscribeGame call in createGame ([f5614c3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f5614c358255598ba1230e42a56b22934d79183c))
|
|
||||||
* 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))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* 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-19)
|
|
||||||
|
|
||||||
### 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:** add GameWritebackEventDto to reflection targets ([87f29a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/87f29a720422f538ef70699533500e060337b8ea))
|
|
||||||
* **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))
|
|
||||||
* **core:** add logs to trace subscribeGame call in createGame ([f5614c3](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f5614c358255598ba1230e42a56b22934d79183c))
|
|
||||||
* 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))
|
|
||||||
* resolve 6 coordinator bugs (cache eviction, rebalance race, pod matching, lookup inefficiency) ([5619c82](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/5619c8223ad7091706909eda8c907a29d215fd30))
|
|
||||||
* 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,6 +75,7 @@ nowchess:
|
|||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
http:
|
http:
|
||||||
|
root-path: /api
|
||||||
cors:
|
cors:
|
||||||
~: true
|
~: true
|
||||||
origins: ${CORS_ORIGINS}
|
origins: ${CORS_ORIGINS}
|
||||||
|
|||||||
@@ -4,17 +4,14 @@ 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],
|
||||||
classOf[GameWritebackEventDto],
|
|
||||||
classOf[GameFullDto],
|
classOf[GameFullDto],
|
||||||
classOf[GameFullEventDto],
|
classOf[GameFullEventDto],
|
||||||
classOf[GameStateDto],
|
classOf[GameStateDto],
|
||||||
|
|||||||
@@ -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.errorf(ex, "IO gRPC exportCombined failed")
|
log.warnf(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.errorf(ex, "IO gRPC importFen failed for fen %s", fen)
|
log.warnf(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.errorf(ex, "IO gRPC importPgn failed")
|
log.warnf(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.errorf(ex, "IO gRPC exportFen failed")
|
log.warnf(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.errorf(ex, "IO gRPC exportPgn failed")
|
log.warnf(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,12 +1,13 @@
|
|||||||
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.{GameStateDto, GameStateEventDto, GameWritebackEventDto}
|
import de.nowchess.api.dto.{GameStateEventDto, GameWritebackEventDto}
|
||||||
import de.nowchess.api.game.{CorrespondenceClockState, DrawReason, GameResult, LiveClockState, TimeControl, WinReason}
|
import de.nowchess.api.game.{CorrespondenceClockState, LiveClockState}
|
||||||
import de.nowchess.api.board.Color
|
|
||||||
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
import de.nowchess.chess.grpc.IoGrpcClientWrapper
|
||||||
|
import de.nowchess.api.game.{DrawReason, GameResult, WinReason}
|
||||||
|
import de.nowchess.api.board.Color
|
||||||
import de.nowchess.chess.observer.{GameEvent, Observer}
|
import de.nowchess.chess.observer.{GameEvent, Observer}
|
||||||
import de.nowchess.chess.registry.{GameEntry, GameRegistry}
|
import de.nowchess.chess.registry.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
|
||||||
@@ -25,69 +26,61 @@ 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)
|
||||||
redis.pubsub(classOf[String]).publish(s2cTopicName, objectMapper.writeValueAsString(GameStateEventDto(dto)))
|
val json = objectMapper.writeValueAsString(GameStateEventDto(dto))
|
||||||
writebackEmit(objectMapper.writeValueAsString(buildWriteback(entry, dto)))
|
redis.pubsub(classOf[String]).publish(s2cTopicName, json)
|
||||||
|
|
||||||
|
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),
|
|
||||||
)
|
|
||||||
|
|||||||
+12
-39
@@ -13,14 +13,12 @@ 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
|
||||||
import jakarta.inject.Inject
|
import jakarta.inject.Inject
|
||||||
import org.jboss.logging.Logger
|
import org.jboss.logging.Logger
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
@@ -47,30 +45,6 @@ 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"
|
||||||
|
|
||||||
@@ -78,8 +52,7 @@ class GameRedisSubscriberManager:
|
|||||||
s"${redisConfig.prefix}:game:$gameId:s2c"
|
s"${redisConfig.prefix}:game:$gameId:s2c"
|
||||||
|
|
||||||
def subscribeGame(gameId: String): Unit =
|
def subscribeGame(gameId: String): Unit =
|
||||||
val writebackFn: String => Unit = json =>
|
val writebackFn: String => Unit = json => redis.pubsub(classOf[String]).publish("game-writeback", json)
|
||||||
redis.stream(classOf[String]).xadd(s"${redisConfig.prefix}:game-writeback", Map("data" -> json).asJava)
|
|
||||||
val obs = new GameRedisPublisher(
|
val obs = new GameRedisPublisher(
|
||||||
gameId,
|
gameId,
|
||||||
registry,
|
registry,
|
||||||
@@ -92,19 +65,20 @@ 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)
|
||||||
try
|
reactiveRedis
|
||||||
val subscriber = reactiveRedis
|
.pubsub(classOf[String])
|
||||||
.pubsub(classOf[String])
|
.subscribe(c2sTopic(gameId), handler)
|
||||||
.subscribe(c2sTopic(gameId), handler)
|
.subscribe()
|
||||||
.await()
|
.`with`(
|
||||||
.atMost(java.time.Duration.ofSeconds(5))
|
subscriber => {
|
||||||
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 =>
|
||||||
@@ -184,6 +158,5 @@ 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)))
|
||||||
|
|||||||
@@ -22,5 +22,4 @@ case class GameCacheDto(
|
|||||||
pendingDrawOffer: Option[String],
|
pendingDrawOffer: Option[String],
|
||||||
redoStack: List[String] = Nil,
|
redoStack: List[String] = Nil,
|
||||||
pendingTakebackRequest: Option[String] = None,
|
pendingTakebackRequest: Option[String] = None,
|
||||||
lastUpdatedMs: Long = System.currentTimeMillis(),
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ class RedisGameRegistry extends GameRegistry:
|
|||||||
clockMoveDeadline = Option(record.clockMoveDeadline).map(_.longValue),
|
clockMoveDeadline = Option(record.clockMoveDeadline).map(_.longValue),
|
||||||
clockActiveColor = Option(record.clockActiveColor),
|
clockActiveColor = Option(record.clockActiveColor),
|
||||||
pendingDrawOffer = Option(record.pendingDrawOffer),
|
pendingDrawOffer = Option(record.pendingDrawOffer),
|
||||||
lastUpdatedMs = System.currentTimeMillis(),
|
|
||||||
)
|
)
|
||||||
(dto, reconstruct(dto))
|
(dto, reconstruct(dto))
|
||||||
} match
|
} match
|
||||||
|
|||||||
@@ -167,9 +167,7 @@ class GameResource:
|
|||||||
val mode = req.mode.getOrElse(GameMode.Open)
|
val mode = req.mode.getOrElse(GameMode.Open)
|
||||||
val entry = newEntry(GameContext.initial, white, black, tc, mode)
|
val entry = newEntry(GameContext.initial, white, black, tc, mode)
|
||||||
registry.store(entry)
|
registry.store(entry)
|
||||||
log.infof("About to subscribe game %s", entry.gameId)
|
|
||||||
subscriberManager.subscribeGame(entry.gameId)
|
subscriberManager.subscribeGame(entry.gameId)
|
||||||
log.infof("Subscribed game %s", entry.gameId)
|
|
||||||
log.infof(
|
log.infof(
|
||||||
"Game %s created — white=%s black=%s mode=%s",
|
"Game %s created — white=%s black=%s mode=%s",
|
||||||
entry.gameId,
|
entry.gameId,
|
||||||
|
|||||||
+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, 15L, json)
|
.setex(key, 5L, json)
|
||||||
.subscribe()
|
.subscribe()
|
||||||
.`with`(
|
.`with`(
|
||||||
_ => redisHeartbeatPending.set(false),
|
_ => redisHeartbeatPending.set(false),
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=45
|
MINOR=37
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -187,237 +187,3 @@
|
|||||||
### 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))
|
|
||||||
## (2026-05-17)
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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-19)
|
|
||||||
|
|
||||||
### 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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 log message for starting Writeback listener ([b610678](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b610678005de645115f48348e66aa9e6f5deb3d5))
|
|
||||||
* **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-19)
|
|
||||||
|
|
||||||
### 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))
|
|
||||||
* **redis:** add @Startup annotation to GameWritebackStreamListener ([d61fe97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d61fe97b4c8e2db5e34b4a14d995297cc09f9435))
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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 log message for starting Writeback listener ([b610678](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b610678005de645115f48348e66aa9e6f5deb3d5))
|
|
||||||
* **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-19)
|
|
||||||
|
|
||||||
### 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))
|
|
||||||
* **redis:** add @Startup annotation to GameWritebackStreamListener ([d61fe97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d61fe97b4c8e2db5e34b4a14d995297cc09f9435))
|
|
||||||
* **redis:** use ManagedExecutor for asynchronous writeback processing ([af6b0ed](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/af6b0ed8b73724fcc8f20dfccbe6fe8f84fd792d))
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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 log message for starting Writeback listener ([b610678](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b610678005de645115f48348e66aa9e6f5deb3d5))
|
|
||||||
* **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-22)
|
|
||||||
|
|
||||||
### 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:** add GameWritebackEventDtoMixin for JSON deserialization ([381161f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/381161f00345612a1789e08243746083dff884c5))
|
|
||||||
* **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))
|
|
||||||
* **redis:** add @Startup annotation to GameWritebackStreamListener ([d61fe97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d61fe97b4c8e2db5e34b4a14d995297cc09f9435))
|
|
||||||
* **redis:** use ManagedExecutor for asynchronous writeback processing ([af6b0ed](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/af6b0ed8b73724fcc8f20dfccbe6fe8f84fd792d))
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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 log message for starting Writeback listener ([b610678](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b610678005de645115f48348e66aa9e6f5deb3d5))
|
|
||||||
* **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-22)
|
|
||||||
|
|
||||||
### 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:** add GameWritebackEventDtoMixin for JSON deserialization ([381161f](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/381161f00345612a1789e08243746083dff884c5))
|
|
||||||
* **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))
|
|
||||||
* **dto:** update GameWritebackEventDto for JSON deserialization and remove unused mixin ([576e3fe](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/576e3fea9bf1082549ea53efd3288474c42be93d))
|
|
||||||
* 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))
|
|
||||||
* **redis:** add @Startup annotation to GameWritebackStreamListener ([d61fe97](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/d61fe97b4c8e2db5e34b4a14d995297cc09f9435))
|
|
||||||
* **redis:** use ManagedExecutor for asynchronous writeback processing ([af6b0ed](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/af6b0ed8b73724fcc8f20dfccbe6fe8f84fd792d))
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* ensure full hierarchy registration for reflection in NativeReflectionConfig ([ebba729](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ebba729af3265df1619dfbe46fd1945b2a7e30b7))
|
|
||||||
* 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 log message for starting Writeback listener ([b610678](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/b610678005de645115f48348e66aa9e6f5deb3d5))
|
|
||||||
* **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,7 +60,6 @@ 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,6 +30,8 @@ nowchess:
|
|||||||
|
|
||||||
"%deployed":
|
"%deployed":
|
||||||
quarkus:
|
quarkus:
|
||||||
|
http:
|
||||||
|
root-path: /api/store
|
||||||
log:
|
log:
|
||||||
console:
|
console:
|
||||||
json: true
|
json: true
|
||||||
|
|||||||
@@ -9,6 +9,5 @@ import io.quarkus.runtime.annotations.RegisterForReflection
|
|||||||
classOf[GameRecord],
|
classOf[GameRecord],
|
||||||
classOf[GameWritebackEventDto],
|
classOf[GameWritebackEventDto],
|
||||||
),
|
),
|
||||||
registerFullHierarchy = true,
|
|
||||||
)
|
)
|
||||||
class NativeReflectionConfig
|
class NativeReflectionConfig
|
||||||
|
|||||||
+7
-78
@@ -2,22 +2,15 @@ package de.nowchess.store.redis
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import de.nowchess.api.dto.GameWritebackEventDto
|
import de.nowchess.api.dto.GameWritebackEventDto
|
||||||
import de.nowchess.store.config.RedisConfig
|
|
||||||
import de.nowchess.store.service.GameWritebackService
|
import de.nowchess.store.service.GameWritebackService
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import io.quarkus.redis.datasource.stream.{StreamMessage, XGroupCreateArgs, XReadGroupArgs}
|
|
||||||
import io.quarkus.runtime.Startup
|
|
||||||
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.eclipse.microprofile.context.ManagedExecutor
|
|
||||||
import org.jboss.logging.Logger
|
|
||||||
import scala.compiletime.uninitialized
|
import scala.compiletime.uninitialized
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.util.Try
|
||||||
import scala.util.{Failure, Success, Try}
|
import java.util.function.Consumer
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@Startup
|
|
||||||
@ApplicationScoped
|
@ApplicationScoped
|
||||||
class GameWritebackStreamListener:
|
class GameWritebackStreamListener:
|
||||||
@Inject
|
@Inject
|
||||||
@@ -25,76 +18,12 @@ class GameWritebackStreamListener:
|
|||||||
var redis: RedisDataSource = uninitialized
|
var redis: RedisDataSource = uninitialized
|
||||||
@Inject var objectMapper: ObjectMapper = uninitialized
|
@Inject var objectMapper: ObjectMapper = uninitialized
|
||||||
@Inject var writebackService: GameWritebackService = uninitialized
|
@Inject var writebackService: GameWritebackService = uninitialized
|
||||||
@Inject var executor: ManagedExecutor = uninitialized
|
|
||||||
@Inject var redisConfig: RedisConfig = uninitialized
|
|
||||||
// scalafix:on
|
// scalafix:on
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[GameWritebackStreamListener])
|
|
||||||
private val groupName = "store-writeback"
|
|
||||||
|
|
||||||
private def streamKey = s"${redisConfig.prefix}:game-writeback"
|
|
||||||
private def dlqKey = s"${redisConfig.prefix}:game-writeback-dlq"
|
|
||||||
private val maxRetries = 3
|
|
||||||
private val consumerId = UUID.randomUUID().toString
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
def startListening(): Unit =
|
def startListening(): Unit =
|
||||||
createGroupIfAbsent()
|
val handler: Consumer[String] = json =>
|
||||||
executor.submit(new Runnable:
|
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])).toOption
|
||||||
def run(): Unit = pollLoop()
|
.foreach(writebackService.writeBack)
|
||||||
)
|
redis.pubsub(classOf[String]).subscribe("game-writeback", handler)
|
||||||
log.infof("Started listening to game-writeback stream (consumer=%s)", consumerId)
|
()
|
||||||
|
|
||||||
private def createGroupIfAbsent(): Unit =
|
|
||||||
Try(redis.stream(classOf[String]).xgroupCreate(streamKey, groupName, "0", new XGroupCreateArgs().mkstream())) match
|
|
||||||
case Failure(ex) if Option(ex.getMessage).exists(_.contains("BUSYGROUP")) => ()
|
|
||||||
case Failure(ex) => log.warnf(ex, "Failed to create consumer group")
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|
||||||
private def pollLoop(): Unit =
|
|
||||||
while true do
|
|
||||||
Try {
|
|
||||||
val messages = redis.stream(classOf[String]).xreadgroup(
|
|
||||||
groupName,
|
|
||||||
consumerId,
|
|
||||||
streamKey,
|
|
||||||
">",
|
|
||||||
new XReadGroupArgs().count(10).block(java.time.Duration.ofSeconds(2)),
|
|
||||||
)
|
|
||||||
if messages != null then messages.forEach(msg => handleMessage(msg))
|
|
||||||
} match
|
|
||||||
case Failure(ex) => log.warnf(ex, "Error in writeback poll loop")
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|
||||||
private def handleMessage(msg: StreamMessage[String, String, String]): Unit =
|
|
||||||
val payload = msg.payload()
|
|
||||||
val json = payload.get("data")
|
|
||||||
val attempt = Option(payload.get("attempt")).flatMap(_.toIntOption).getOrElse(0)
|
|
||||||
|
|
||||||
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])) match
|
|
||||||
case Failure(ex) =>
|
|
||||||
log.errorf(ex, "Unparseable writeback event, sending to DLQ: %s", json)
|
|
||||||
xadd(dlqKey, json, attempt)
|
|
||||||
ack(msg.id())
|
|
||||||
case Success(event) =>
|
|
||||||
Try(writebackService.writeBack(event)) match
|
|
||||||
case Success(_) =>
|
|
||||||
ack(msg.id())
|
|
||||||
case Failure(ex) if attempt + 1 < maxRetries =>
|
|
||||||
log.warnf(ex, "Writeback failed for gameId=%s attempt=%d, retrying", event.gameId, attempt)
|
|
||||||
xadd(streamKey, json, attempt + 1)
|
|
||||||
ack(msg.id())
|
|
||||||
case Failure(ex) =>
|
|
||||||
log.errorf(ex, "Writeback failed for gameId=%s after %d attempts, sending to DLQ", event.gameId, maxRetries)
|
|
||||||
xadd(dlqKey, json, attempt)
|
|
||||||
ack(msg.id())
|
|
||||||
|
|
||||||
private def ack(id: String): Unit =
|
|
||||||
Try(redis.stream(classOf[String]).xack(streamKey, groupName, id)) match
|
|
||||||
case Failure(ex) => log.warnf(ex, "Failed to ack message %s", id)
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|
||||||
private def xadd(key: String, json: String, attempt: Int): Unit =
|
|
||||||
Try(redis.stream(classOf[String]).xadd(key, Map("data" -> json, "attempt" -> attempt.toString).asJava)) match
|
|
||||||
case Failure(ex) => log.errorf(ex, "Failed to publish to stream %s", key)
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|||||||
@@ -34,19 +34,6 @@ 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",
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
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,7 +8,6 @@ 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
|
||||||
@@ -16,8 +15,6 @@ 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
|
||||||
@@ -49,15 +46,12 @@ 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=22
|
MINOR=13
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("scala")
|
|
||||||
id("org.scoverage") version "8.1"
|
|
||||||
id("io.quarkus")
|
|
||||||
}
|
|
||||||
|
|
||||||
group = "de.nowchess"
|
|
||||||
version = "1.0-SNAPSHOT"
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val versions = rootProject.extra["VERSIONS"] as Map<String, String>
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
scala {
|
|
||||||
scalaVersion = versions["SCALA3"]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
scoverage {
|
|
||||||
scoverageVersion.set(versions["SCOVERAGE"]!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<ScalaCompile> {
|
|
||||||
scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
|
|
||||||
}
|
|
||||||
|
|
||||||
val quarkusPlatformGroupId: String by project
|
|
||||||
val quarkusPlatformArtifactId: String by project
|
|
||||||
val quarkusPlatformVersion: String by project
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":modules:api"))
|
|
||||||
implementation(project(":modules:security"))
|
|
||||||
|
|
||||||
runtimeOnly("io.quarkus:quarkus-jdbc-h2")
|
|
||||||
|
|
||||||
compileOnly("org.scala-lang:scala3-compiler_3") {
|
|
||||||
version {
|
|
||||||
strictly(versions["SCALA3"]!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
implementation("org.scala-lang:scala3-library_3") {
|
|
||||||
version {
|
|
||||||
strictly(versions["SCALA3"]!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implementation(platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
|
|
||||||
implementation("io.quarkus:quarkus-rest")
|
|
||||||
implementation("io.quarkus:quarkus-rest-jackson")
|
|
||||||
implementation("io.quarkus:quarkus-rest-client-jackson")
|
|
||||||
implementation("io.quarkus:quarkus-config-yaml")
|
|
||||||
implementation("io.quarkus:quarkus-arc")
|
|
||||||
implementation("io.quarkus:quarkus-hibernate-orm-panache")
|
|
||||||
implementation("io.quarkus:quarkus-jdbc-postgresql")
|
|
||||||
implementation("io.quarkus:quarkus-smallrye-jwt")
|
|
||||||
implementation("io.quarkus:quarkus-elytron-security-common")
|
|
||||||
implementation("io.quarkus:quarkus-smallrye-health")
|
|
||||||
implementation("io.quarkus:quarkus-logging-json")
|
|
||||||
implementation("io.quarkus:quarkus-micrometer")
|
|
||||||
implementation("io.quarkus:quarkus-micrometer-registry-prometheus")
|
|
||||||
implementation("io.quarkus:quarkus-opentelemetry")
|
|
||||||
implementation("io.quarkus:quarkus-smallrye-openapi")
|
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")
|
|
||||||
implementation("io.quarkus:quarkus-redis-client")
|
|
||||||
|
|
||||||
testImplementation(platform("org.junit:junit-bom:5.13.4"))
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
|
||||||
testImplementation("io.quarkus:quarkus-smallrye-jwt-build")
|
|
||||||
testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
|
|
||||||
testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
|
|
||||||
testImplementation("io.quarkus:quarkus-junit5")
|
|
||||||
testImplementation("io.quarkus:quarkus-junit5-mockito")
|
|
||||||
testImplementation("io.rest-assured:rest-assured")
|
|
||||||
testImplementation("io.quarkus:quarkus-jdbc-h2")
|
|
||||||
testImplementation("io.quarkus:quarkus-test-security")
|
|
||||||
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations.matching { !it.name.startsWith("scoverage") }.configureEach {
|
|
||||||
resolutionStrategy.force("org.scala-lang:scala-library:${versions["SCALA_LIBRARY"]!!}")
|
|
||||||
}
|
|
||||||
configurations.scoverage {
|
|
||||||
resolutionStrategy.eachDependency {
|
|
||||||
if (requested.group == "org.scoverage" && requested.name.startsWith("scalac-scoverage-plugin_")) {
|
|
||||||
useTarget("${requested.group}:scalac-scoverage-plugin_2.13.16:2.3.0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<JavaCompile> {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
options.compilerArgs.add("-parameters")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<Jar>().configureEach {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform {
|
|
||||||
includeEngines("scalatest", "junit-jupiter")
|
|
||||||
testLogging {
|
|
||||||
events("passed", "skipped", "failed")
|
|
||||||
showStandardStreams = true
|
|
||||||
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finalizedBy(tasks.reportScoverage)
|
|
||||||
}
|
|
||||||
tasks.reportScoverage {
|
|
||||||
dependsOn(tasks.test)
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.jar {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
quarkus:
|
|
||||||
http:
|
|
||||||
port: 8088
|
|
||||||
application:
|
|
||||||
name: nowchess-tournament
|
|
||||||
redis:
|
|
||||||
hosts: redis://${REDIS_HOST:localhost}:${REDIS_PORT:6379}
|
|
||||||
rest-client:
|
|
||||||
core-service:
|
|
||||||
url: http://localhost:8080
|
|
||||||
datasource:
|
|
||||||
db-kind: h2
|
|
||||||
username: sa
|
|
||||||
password: ""
|
|
||||||
jdbc:
|
|
||||||
url: jdbc:h2:mem:nowchess-tournament;DB_CLOSE_DELAY=-1
|
|
||||||
hibernate-orm:
|
|
||||||
schema-management:
|
|
||||||
strategy: drop-and-create
|
|
||||||
smallrye-jwt:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
nowchess:
|
|
||||||
redis:
|
|
||||||
host: ${REDIS_HOST:localhost}
|
|
||||||
port: ${REDIS_PORT:6379}
|
|
||||||
prefix: ${REDIS_PREFIX:nowchess}
|
|
||||||
internal:
|
|
||||||
secret: ${INTERNAL_SECRET:123abc}
|
|
||||||
|
|
||||||
mp:
|
|
||||||
jwt:
|
|
||||||
verify:
|
|
||||||
publickey:
|
|
||||||
location: keys/public.pem
|
|
||||||
issuer: nowchess
|
|
||||||
|
|
||||||
"%deployed":
|
|
||||||
quarkus:
|
|
||||||
datasource:
|
|
||||||
db-kind: postgresql
|
|
||||||
username: ${DB_USER:nowchess}
|
|
||||||
password: ${DB_PASSWORD:nowchess}
|
|
||||||
jdbc:
|
|
||||||
url: ${DB_URL:jdbc:postgresql://localhost:5432/nowchess}
|
|
||||||
hibernate-orm:
|
|
||||||
schema-management:
|
|
||||||
strategy: update
|
|
||||||
|
|
||||||
"%test":
|
|
||||||
quarkus:
|
|
||||||
datasource:
|
|
||||||
jdbc:
|
|
||||||
url: jdbc:h2:mem:nowchess-tournament;DB_CLOSE_DELAY=-1
|
|
||||||
hibernate-orm:
|
|
||||||
schema-management:
|
|
||||||
strategy: drop-and-create
|
|
||||||
arc:
|
|
||||||
exclude-types: de.nowchess.tournament.redis.GameResultStreamListener
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxDsnsCAl0vQx7Vu9CLDZ
|
|
||||||
g0SG05NgUzu9T+3DTEaHGq60T2uriO8BenwyvsF3BnDqTbKf4voohZ1DNfzdbT1J
|
|
||||||
Fj8B62FrDmxcO+sp1/b5HUCJP6y2uSRCmzOHe5k7Pk1IEi72FgBpKXSRkFibRlVf
|
|
||||||
634g7mgsPZAQ9PJEsv4Qvm05T9L6+Gmq6N3bMVLKRXs4RhDhaFbYH9GtUg1eI0yH
|
|
||||||
YjGyRfqzW/nqVMstOLHt8CuPouq4p7eMzeDH3YHkxPm4GG5foCXMOd2DZrW0SCcr
|
|
||||||
7dhFeNVWzQ2m53eOhBzNQX+v3pgjVStsePhBRt2LyGfwkNzmqDgqWsMzSHRMY+cn
|
|
||||||
WQIDAQAB
|
|
||||||
-----END PUBLIC KEY-----
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package de.nowchess.tournament.client
|
|
||||||
|
|
||||||
import de.nowchess.security.{InternalClientHeadersFactory, InternalSecretClientFilter}
|
|
||||||
import jakarta.ws.rs.*
|
|
||||||
import jakarta.ws.rs.core.MediaType
|
|
||||||
import org.eclipse.microprofile.rest.client.annotation.{RegisterClientHeaders, RegisterProvider}
|
|
||||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient
|
|
||||||
|
|
||||||
case class CorePlayerInfo(id: String, displayName: String)
|
|
||||||
case class CoreTimeControl(limitSeconds: Option[Int], incrementSeconds: Option[Int], daysPerMove: Option[Int])
|
|
||||||
case class CoreCreateGameRequest(
|
|
||||||
white: Option[CorePlayerInfo],
|
|
||||||
black: Option[CorePlayerInfo],
|
|
||||||
timeControl: Option[CoreTimeControl],
|
|
||||||
mode: Option[String],
|
|
||||||
)
|
|
||||||
case class CoreGameResponse(gameId: String)
|
|
||||||
|
|
||||||
@Path("/api/board/game")
|
|
||||||
@RegisterRestClient(configKey = "core-service")
|
|
||||||
@RegisterProvider(classOf[InternalSecretClientFilter])
|
|
||||||
@RegisterClientHeaders(classOf[InternalClientHeadersFactory])
|
|
||||||
trait CoreGameClient:
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
|
||||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
|
||||||
def createGame(req: CoreCreateGameRequest): CoreGameResponse
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package de.nowchess.tournament.config
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
|
||||||
import io.quarkus.jackson.ObjectMapperCustomizer
|
|
||||||
import jakarta.inject.Singleton
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
class JacksonConfig extends ObjectMapperCustomizer:
|
|
||||||
def customize(objectMapper: ObjectMapper): Unit =
|
|
||||||
objectMapper.registerModule(DefaultScalaModule)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package de.nowchess.tournament.config
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import org.eclipse.microprofile.config.inject.ConfigProperty
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class RedisConfig:
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@ConfigProperty(name = "nowchess.redis.prefix", defaultValue = "nowchess")
|
|
||||||
var prefix: String = uninitialized
|
|
||||||
// scalafix:on DisableSyntax.var
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package de.nowchess.tournament.domain
|
|
||||||
|
|
||||||
import jakarta.persistence.*
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "tournaments")
|
|
||||||
class Tournament:
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Id
|
|
||||||
var id: String = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var fullName: String = uninitialized
|
|
||||||
|
|
||||||
var nbRounds: Int = 0
|
|
||||||
var clockLimit: Int = 0
|
|
||||||
var clockIncrement: Int = 0
|
|
||||||
var rated: Boolean = true
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var status: String = "created"
|
|
||||||
|
|
||||||
var currentRound: Int = 0
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var createdBy: String = uninitialized
|
|
||||||
|
|
||||||
var startsAt: Instant = uninitialized
|
|
||||||
var winnerId: String = uninitialized
|
|
||||||
var winnerName: String = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
package de.nowchess.tournament.domain
|
|
||||||
|
|
||||||
import jakarta.persistence.*
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "tournament_pairings")
|
|
||||||
class TournamentPairing:
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.UUID)
|
|
||||||
var id: UUID = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var tournamentId: String = uninitialized
|
|
||||||
|
|
||||||
var round: Int = 0
|
|
||||||
var whiteId: String = uninitialized
|
|
||||||
var whiteName: String = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var blackId: String = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var blackName: String = uninitialized
|
|
||||||
|
|
||||||
var gameId: String = uninitialized
|
|
||||||
var winner: String = uninitialized
|
|
||||||
var moveList: String = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
package de.nowchess.tournament.domain
|
|
||||||
|
|
||||||
import jakarta.persistence.*
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "tournament_participants")
|
|
||||||
class TournamentParticipant:
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.UUID)
|
|
||||||
var id: UUID = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var tournamentId: String = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var botId: String = uninitialized
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
var botName: String = uninitialized
|
|
||||||
|
|
||||||
var points: Double = 0.0
|
|
||||||
var tieBreak: Double = 0.0
|
|
||||||
var nbGames: Int = 0
|
|
||||||
var wins: Int = 0
|
|
||||||
var draws: Int = 0
|
|
||||||
var losses: Int = 0
|
|
||||||
var byeCount: Int = 0
|
|
||||||
// scalafix:on
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
package de.nowchess.tournament.dto
|
|
||||||
|
|
||||||
case class BotRef(id: String, name: String)
|
|
||||||
|
|
||||||
case class Clock(limit: Int, increment: Int)
|
|
||||||
|
|
||||||
case class Variant(key: String, name: String)
|
|
||||||
|
|
||||||
case class CreateTournamentForm(
|
|
||||||
name: String,
|
|
||||||
nbRounds: Int,
|
|
||||||
clockLimit: Int,
|
|
||||||
clockIncrement: Int,
|
|
||||||
rated: Boolean = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
case class ResultDto(
|
|
||||||
rank: Int,
|
|
||||||
points: Double,
|
|
||||||
tieBreak: Double,
|
|
||||||
bot: BotRef,
|
|
||||||
nbGames: Int,
|
|
||||||
wins: Int,
|
|
||||||
draws: Int,
|
|
||||||
losses: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
case class Standing(page: Int, players: List[ResultDto])
|
|
||||||
|
|
||||||
case class TournamentDto(
|
|
||||||
id: String,
|
|
||||||
fullName: String,
|
|
||||||
clock: Clock,
|
|
||||||
variant: Variant,
|
|
||||||
rated: Boolean,
|
|
||||||
nbPlayers: Int,
|
|
||||||
nbRounds: Int,
|
|
||||||
createdBy: String,
|
|
||||||
startsAt: Option[String],
|
|
||||||
status: String,
|
|
||||||
round: Int,
|
|
||||||
standing: Standing,
|
|
||||||
winner: Option[BotRef],
|
|
||||||
)
|
|
||||||
|
|
||||||
case class TournamentListDto(
|
|
||||||
created: List[TournamentDto],
|
|
||||||
started: List[TournamentDto],
|
|
||||||
finished: List[TournamentDto],
|
|
||||||
)
|
|
||||||
|
|
||||||
case class PairingDto(
|
|
||||||
id: String,
|
|
||||||
round: Int,
|
|
||||||
white: Option[BotRef],
|
|
||||||
black: BotRef,
|
|
||||||
gameId: Option[String],
|
|
||||||
winner: Option[String],
|
|
||||||
)
|
|
||||||
|
|
||||||
case class GameExportDto(
|
|
||||||
id: String,
|
|
||||||
round: Int,
|
|
||||||
white: BotRef,
|
|
||||||
black: BotRef,
|
|
||||||
winner: Option[String],
|
|
||||||
moves: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
case class RoundPairingsDto(round: Int, pairings: List[PairingDto])
|
|
||||||
|
|
||||||
case class ErrorDto(error: String)
|
|
||||||
|
|
||||||
case class OkDto(ok: Boolean = true)
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package de.nowchess.tournament.error
|
|
||||||
|
|
||||||
enum TournamentError(val message: String):
|
|
||||||
case NotFound(id: String) extends TournamentError(s"Tournament $id not found")
|
|
||||||
case NotDirector extends TournamentError("Not the tournament director")
|
|
||||||
case WrongStatus(expected: String) extends TournamentError(s"Tournament must be in $expected status")
|
|
||||||
case AlreadyJoined extends TournamentError("Already joined this tournament")
|
|
||||||
case NotJoined extends TournamentError("Not joined this tournament")
|
|
||||||
case NotEnoughParticipants extends TournamentError("Need at least 2 participants to start")
|
|
||||||
case NotABot extends TournamentError("Only bot accounts can join tournaments")
|
|
||||||
-82
@@ -1,82 +0,0 @@
|
|||||||
package de.nowchess.tournament.redis
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
|
||||||
import de.nowchess.api.dto.GameWritebackEventDto
|
|
||||||
import de.nowchess.tournament.config.RedisConfig
|
|
||||||
import de.nowchess.tournament.service.TournamentService
|
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
|
||||||
import io.quarkus.redis.datasource.stream.{StreamMessage, XGroupCreateArgs, XReadGroupArgs}
|
|
||||||
import io.quarkus.runtime.Startup
|
|
||||||
import jakarta.annotation.PostConstruct
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import org.eclipse.microprofile.context.ManagedExecutor
|
|
||||||
import org.jboss.logging.Logger
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
import scala.util.{Failure, Success, Try}
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@Startup
|
|
||||||
@ApplicationScoped
|
|
||||||
class GameResultStreamListener:
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Inject var redis: RedisDataSource = uninitialized
|
|
||||||
@Inject var objectMapper: ObjectMapper = uninitialized
|
|
||||||
@Inject var tournamentService: TournamentService = uninitialized
|
|
||||||
@Inject var executor: ManagedExecutor = uninitialized
|
|
||||||
@Inject var redisConfig: RedisConfig = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[GameResultStreamListener])
|
|
||||||
private val groupName = "tournament-result"
|
|
||||||
private val consumerId = UUID.randomUUID().toString
|
|
||||||
|
|
||||||
private def streamKey = s"${redisConfig.prefix}:game-writeback"
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
def startListening(): Unit =
|
|
||||||
createGroupIfAbsent()
|
|
||||||
executor.submit(new Runnable:
|
|
||||||
def run(): Unit = pollLoop()
|
|
||||||
)
|
|
||||||
log.infof("Tournament result listener started (consumer=%s)", consumerId)
|
|
||||||
|
|
||||||
private def createGroupIfAbsent(): Unit =
|
|
||||||
Try(redis.stream(classOf[String]).xgroupCreate(streamKey, groupName, "0", new XGroupCreateArgs().mkstream())) match
|
|
||||||
case Failure(ex) if Option(ex.getMessage).exists(_.contains("BUSYGROUP")) => ()
|
|
||||||
case Failure(ex) => log.warnf(ex, "Failed to create consumer group")
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|
||||||
private def pollLoop(): Unit =
|
|
||||||
while true do
|
|
||||||
Try {
|
|
||||||
val messages = redis.stream(classOf[String]).xreadgroup(
|
|
||||||
groupName,
|
|
||||||
consumerId,
|
|
||||||
streamKey,
|
|
||||||
">",
|
|
||||||
new XReadGroupArgs().count(10).block(java.time.Duration.ofSeconds(2)),
|
|
||||||
)
|
|
||||||
if messages != null then messages.forEach(msg => handleMessage(msg))
|
|
||||||
} match
|
|
||||||
case Failure(ex) => log.warnf(ex, "Error in result poll loop")
|
|
||||||
case Success(_) => ()
|
|
||||||
|
|
||||||
private def handleMessage(msg: StreamMessage[String, String, String]): Unit =
|
|
||||||
val json = msg.payload().get("data")
|
|
||||||
Try(objectMapper.readValue(json, classOf[GameWritebackEventDto])) match
|
|
||||||
case Failure(ex) =>
|
|
||||||
log.errorf(ex, "Unparseable game result event: %s", json)
|
|
||||||
ack(msg.id())
|
|
||||||
case Success(event) =>
|
|
||||||
if event.result.isDefined then
|
|
||||||
Try(tournamentService.handleGameResult(event.gameId, event.result.get, event.pgn)) match
|
|
||||||
case Failure(ex) => log.errorf(ex, "Failed to handle game result for %s", event.gameId)
|
|
||||||
case Success(_) => ()
|
|
||||||
ack(msg.id())
|
|
||||||
|
|
||||||
private def ack(id: String): Unit =
|
|
||||||
Try(redis.stream(classOf[String]).xack(streamKey, groupName, id)) match
|
|
||||||
case Failure(ex) => log.warnf(ex, "Failed to ack message %s", id)
|
|
||||||
case Success(_) => ()
|
|
||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
package de.nowchess.tournament.repository
|
|
||||||
|
|
||||||
import de.nowchess.tournament.domain.TournamentPairing
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import jakarta.persistence.EntityManager
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class PairingRepository:
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
var em: EntityManager = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
def findByTournamentId(tournamentId: String): List[TournamentPairing] =
|
|
||||||
em.createQuery("FROM TournamentPairing WHERE tournamentId = :tid", classOf[TournamentPairing])
|
|
||||||
.setParameter("tid", tournamentId)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.toList
|
|
||||||
|
|
||||||
def findByTournamentIdAndRound(tournamentId: String, round: Int): List[TournamentPairing] =
|
|
||||||
em.createQuery(
|
|
||||||
"FROM TournamentPairing WHERE tournamentId = :tid AND round = :round",
|
|
||||||
classOf[TournamentPairing],
|
|
||||||
).setParameter("tid", tournamentId)
|
|
||||||
.setParameter("round", round)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.toList
|
|
||||||
|
|
||||||
def findByGameId(gameId: String): Option[TournamentPairing] =
|
|
||||||
em.createQuery("FROM TournamentPairing WHERE gameId = :gid", classOf[TournamentPairing])
|
|
||||||
.setParameter("gid", gameId)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.headOption
|
|
||||||
|
|
||||||
def persist(p: TournamentPairing): TournamentPairing =
|
|
||||||
if p.id == null then
|
|
||||||
em.persist(p)
|
|
||||||
p
|
|
||||||
else em.merge(p)
|
|
||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
package de.nowchess.tournament.repository
|
|
||||||
|
|
||||||
import de.nowchess.tournament.domain.TournamentParticipant
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import jakarta.persistence.EntityManager
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class ParticipantRepository:
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
var em: EntityManager = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
def findByTournamentId(tournamentId: String): List[TournamentParticipant] =
|
|
||||||
em.createQuery("FROM TournamentParticipant WHERE tournamentId = :tid", classOf[TournamentParticipant])
|
|
||||||
.setParameter("tid", tournamentId)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.toList
|
|
||||||
|
|
||||||
def findByTournamentIdAndBotId(tournamentId: String, botId: String): Option[TournamentParticipant] =
|
|
||||||
em.createQuery(
|
|
||||||
"FROM TournamentParticipant WHERE tournamentId = :tid AND botId = :bid",
|
|
||||||
classOf[TournamentParticipant],
|
|
||||||
).setParameter("tid", tournamentId)
|
|
||||||
.setParameter("bid", botId)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.headOption
|
|
||||||
|
|
||||||
def persist(p: TournamentParticipant): TournamentParticipant =
|
|
||||||
if p.id == null then
|
|
||||||
em.persist(p)
|
|
||||||
p
|
|
||||||
else em.merge(p)
|
|
||||||
|
|
||||||
def delete(p: TournamentParticipant): Unit =
|
|
||||||
em.remove(if em.contains(p) then p else em.merge(p))
|
|
||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
package de.nowchess.tournament.repository
|
|
||||||
|
|
||||||
import de.nowchess.tournament.domain.Tournament
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import jakarta.persistence.EntityManager
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class TournamentRepository:
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
var em: EntityManager = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
def findOptById(id: String): Option[Tournament] =
|
|
||||||
Option(em.find(classOf[Tournament], id))
|
|
||||||
|
|
||||||
def findByStatus(status: String): List[Tournament] =
|
|
||||||
em.createQuery("FROM Tournament WHERE status = :status", classOf[Tournament])
|
|
||||||
.setParameter("status", status)
|
|
||||||
.getResultList
|
|
||||||
.asScala
|
|
||||||
.toList
|
|
||||||
|
|
||||||
def persist(t: Tournament): Tournament =
|
|
||||||
if em.contains(t) then t else em.merge(t)
|
|
||||||
|
|
||||||
def delete(t: Tournament): Unit =
|
|
||||||
val managed = if em.contains(t) then t else em.merge(t)
|
|
||||||
em.remove(managed)
|
|
||||||
-184
@@ -1,184 +0,0 @@
|
|||||||
package de.nowchess.tournament.resource
|
|
||||||
|
|
||||||
import de.nowchess.tournament.dto.*
|
|
||||||
import de.nowchess.tournament.error.TournamentError
|
|
||||||
import de.nowchess.tournament.service.{TournamentService, TournamentStreamManager}
|
|
||||||
import io.smallrye.mutiny.Multi
|
|
||||||
import jakarta.annotation.security.{PermitAll, RolesAllowed}
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import jakarta.ws.rs.*
|
|
||||||
import jakarta.ws.rs.core.{Context, HttpHeaders, MediaType, Response}
|
|
||||||
import org.eclipse.microprofile.jwt.JsonWebToken
|
|
||||||
import org.jboss.logging.Logger
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
|
|
||||||
@Path("/api/tournament")
|
|
||||||
@ApplicationScoped
|
|
||||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
|
||||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
|
||||||
class TournamentResource:
|
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[TournamentResource])
|
|
||||||
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Inject var tournamentService: TournamentService = uninitialized
|
|
||||||
@Inject var streamManager: TournamentStreamManager = uninitialized
|
|
||||||
@Inject var jwt: JsonWebToken = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@PermitAll
|
|
||||||
def list(): Response =
|
|
||||||
val (created, started, finished) = tournamentService.list()
|
|
||||||
val dto = TournamentListDto(
|
|
||||||
created = created.map(t => tournamentService.toDto(t)),
|
|
||||||
started = started.map(t => tournamentService.toDto(t)),
|
|
||||||
finished = finished.map(t => tournamentService.toDto(t)),
|
|
||||||
)
|
|
||||||
Response.ok(dto).build()
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
@Consumes(Array(MediaType.APPLICATION_FORM_URLENCODED))
|
|
||||||
def create(
|
|
||||||
@FormParam("name") name: String,
|
|
||||||
@FormParam("nbRounds") nbRounds: Int,
|
|
||||||
@FormParam("clockLimit") clockLimit: Int,
|
|
||||||
@FormParam("clockIncrement") clockIncrement: Int,
|
|
||||||
@FormParam("rated") @DefaultValue("true") rated: Boolean,
|
|
||||||
): Response =
|
|
||||||
val userId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
val form = CreateTournamentForm(name, nbRounds, clockLimit, clockIncrement, rated)
|
|
||||||
val t = tournamentService.create(userId, form)
|
|
||||||
Response.status(Response.Status.CREATED).entity(tournamentService.toDto(t)).build()
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}")
|
|
||||||
@PermitAll
|
|
||||||
def get(@PathParam("id") id: String): Response =
|
|
||||||
tournamentService.get(id) match
|
|
||||||
case None => Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(s"Tournament $id not found")).build()
|
|
||||||
case Some(t) =>
|
|
||||||
val standings = tournamentService.getStandings(id)
|
|
||||||
Response.ok(tournamentService.toDto(t, standings)).build()
|
|
||||||
|
|
||||||
@DELETE
|
|
||||||
@Path("/{id}")
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
def terminate(@PathParam("id") id: String): Response =
|
|
||||||
val userId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
tournamentService.terminate(id, userId) match
|
|
||||||
case Right(_) => Response.noContent().build()
|
|
||||||
case Left(error) => errorResponse(error)
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/{id}/start")
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
def start(@PathParam("id") id: String): Response =
|
|
||||||
val userId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
tournamentService.start(id, userId) match
|
|
||||||
case Right(t) => Response.ok(tournamentService.toDto(t)).build()
|
|
||||||
case Left(error) => errorResponse(error)
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/{id}/join")
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
def join(@PathParam("id") id: String): Response =
|
|
||||||
val tokenType = Option(jwt.getClaim[AnyRef]("type")).map(_.toString).getOrElse("")
|
|
||||||
if tokenType != "bot" then
|
|
||||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto("Only bots can join tournaments")).build()
|
|
||||||
else
|
|
||||||
val botId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
val botName = Option(jwt.getClaim[AnyRef]("name")).map(_.toString).getOrElse(botId)
|
|
||||||
tournamentService.join(id, botId, botName) match
|
|
||||||
case Right(_) => Response.ok(OkDto()).build()
|
|
||||||
case Left(error) => errorResponse(error)
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/{id}/withdraw")
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
def withdraw(@PathParam("id") id: String): Response =
|
|
||||||
val tokenType = Option(jwt.getClaim[AnyRef]("type")).map(_.toString).getOrElse("")
|
|
||||||
if tokenType != "bot" then
|
|
||||||
Response.status(Response.Status.FORBIDDEN).entity(ErrorDto("Only bots can withdraw")).build()
|
|
||||||
else
|
|
||||||
val botId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
tournamentService.withdraw(id, botId) match
|
|
||||||
case Right(_) => Response.ok(OkDto()).build()
|
|
||||||
case Left(error) => errorResponse(error)
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}/results")
|
|
||||||
@Produces(Array("application/x-ndjson"))
|
|
||||||
@PermitAll
|
|
||||||
def results(
|
|
||||||
@PathParam("id") id: String,
|
|
||||||
@QueryParam("nb") @DefaultValue("100") nb: Int,
|
|
||||||
): Response =
|
|
||||||
tournamentService.get(id) match
|
|
||||||
case None => Response.status(Response.Status.NOT_FOUND).entity("").build()
|
|
||||||
case Some(_) =>
|
|
||||||
val ndjson = tournamentService.getResults(id).take(nb).map { r =>
|
|
||||||
s"""{"rank":${r.rank},"points":${r.points},"tieBreak":${r.tieBreak},"bot":{"id":"${r.bot.id}","name":"${r.bot.name}"},"nbGames":${r.nbGames},"wins":${r.wins},"draws":${r.draws},"losses":${r.losses}}"""
|
|
||||||
}.mkString("\n")
|
|
||||||
Response.ok(ndjson).`type`("application/x-ndjson").build()
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}/round/{round}")
|
|
||||||
@PermitAll
|
|
||||||
def roundPairings(@PathParam("id") id: String, @PathParam("round") round: Int): Response =
|
|
||||||
tournamentService.get(id) match
|
|
||||||
case None => Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(s"Tournament $id not found")).build()
|
|
||||||
case Some(_) =>
|
|
||||||
val pairings = tournamentService.getPairings(id, round)
|
|
||||||
Response.ok(RoundPairingsDto(round, pairings)).build()
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}/export/games")
|
|
||||||
@PermitAll
|
|
||||||
@Produces(Array(MediaType.APPLICATION_JSON, MediaType.WILDCARD, "application/x-ndjson", "application/x-chess-pgn"))
|
|
||||||
def exportGames(@PathParam("id") id: String, @Context headers: HttpHeaders): Response =
|
|
||||||
tournamentService.get(id) match
|
|
||||||
case None => Response.status(Response.Status.NOT_FOUND).entity(ErrorDto(s"Tournament $id not found")).build()
|
|
||||||
case Some(_) =>
|
|
||||||
val acceptHeader = Option(headers.getHeaderString("Accept")).getOrElse("")
|
|
||||||
val pairings = tournamentService.getAllPairings(id)
|
|
||||||
if acceptHeader.contains("application/x-ndjson") then
|
|
||||||
val ndjson = pairings
|
|
||||||
.filter(p => Option(p.whiteId).isDefined && Option(p.gameId).isDefined)
|
|
||||||
.map { p =>
|
|
||||||
val winner = Option(p.winner).map(w => s""""$w"""").getOrElse("null")
|
|
||||||
val moves = Option(p.moveList).getOrElse("")
|
|
||||||
s"""{"id":"${p.gameId}","round":${p.round},"white":{"id":"${p.whiteId}","name":"${p.whiteName}"},"black":{"id":"${p.blackId}","name":"${p.blackName}"},"winner":$winner,"moves":"$moves"}"""
|
|
||||||
}
|
|
||||||
.mkString("\n")
|
|
||||||
Response.ok(ndjson).`type`("application/x-ndjson").build()
|
|
||||||
else
|
|
||||||
val pgn = pairings.flatMap(p => Option(p.moveList)).mkString("\n\n")
|
|
||||||
Response.ok(pgn).`type`("application/x-chess-pgn").build()
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{id}/stream")
|
|
||||||
@RolesAllowed(Array("**"))
|
|
||||||
@Produces(Array("application/x-ndjson"))
|
|
||||||
def stream(@PathParam("id") id: String): Multi[String] =
|
|
||||||
tournamentService.get(id) match
|
|
||||||
case None => Multi.createFrom().failure(new NotFoundException(s"Tournament $id not found"))
|
|
||||||
case Some(_) =>
|
|
||||||
val botId = Option(jwt.getSubject).getOrElse("")
|
|
||||||
Multi.createFrom().emitter[String] { emitter =>
|
|
||||||
streamManager.register(id, botId, emitter)
|
|
||||||
emitter.onTermination(() => streamManager.unregister(id, botId, emitter))
|
|
||||||
}
|
|
||||||
|
|
||||||
private def errorResponse(error: TournamentError): Response =
|
|
||||||
val status = error match
|
|
||||||
case TournamentError.NotFound(_) => Response.Status.NOT_FOUND
|
|
||||||
case TournamentError.NotDirector => Response.Status.FORBIDDEN
|
|
||||||
case TournamentError.NotABot => Response.Status.FORBIDDEN
|
|
||||||
case TournamentError.WrongStatus(_) => Response.Status.CONFLICT
|
|
||||||
case TournamentError.AlreadyJoined => Response.Status.CONFLICT
|
|
||||||
case TournamentError.NotJoined => Response.Status.CONFLICT
|
|
||||||
case TournamentError.NotEnoughParticipants => Response.Status.CONFLICT
|
|
||||||
Response.status(status).entity(ErrorDto(error.message)).build()
|
|
||||||
-68
@@ -1,68 +0,0 @@
|
|||||||
package de.nowchess.tournament.service
|
|
||||||
|
|
||||||
import de.nowchess.tournament.domain.{TournamentParticipant, TournamentPairing}
|
|
||||||
import java.util.concurrent.ThreadLocalRandom
|
|
||||||
|
|
||||||
object SwissPairingService:
|
|
||||||
|
|
||||||
def computePairings(
|
|
||||||
participants: List[TournamentParticipant],
|
|
||||||
pastPairings: List[TournamentPairing],
|
|
||||||
): (List[(TournamentParticipant, TournamentParticipant)], Option[TournamentParticipant]) =
|
|
||||||
val sorted = sortParticipants(participants)
|
|
||||||
val (remaining, byeOpt) = extractByePlayer(sorted)
|
|
||||||
val pairs = buildPairs(remaining, pastPairings)
|
|
||||||
(pairs, byeOpt)
|
|
||||||
|
|
||||||
private def sortParticipants(participants: List[TournamentParticipant]): List[TournamentParticipant] =
|
|
||||||
participants.sortWith { (a, b) =>
|
|
||||||
if a.points != b.points then a.points > b.points
|
|
||||||
else if a.tieBreak != b.tieBreak then a.tieBreak > b.tieBreak
|
|
||||||
else a.botName < b.botName
|
|
||||||
}
|
|
||||||
|
|
||||||
private def extractByePlayer(
|
|
||||||
sorted: List[TournamentParticipant],
|
|
||||||
): (List[TournamentParticipant], Option[TournamentParticipant]) =
|
|
||||||
if sorted.size % 2 == 0 then (sorted, None)
|
|
||||||
else
|
|
||||||
val minByes = sorted.map(_.byeCount).min
|
|
||||||
val byeIndex = sorted.lastIndexWhere(_.byeCount == minByes)
|
|
||||||
val bye = sorted(byeIndex)
|
|
||||||
(sorted.filterNot(_ eq bye), Some(bye))
|
|
||||||
|
|
||||||
private def buildPairs(
|
|
||||||
players: List[TournamentParticipant],
|
|
||||||
pastPairings: List[TournamentPairing],
|
|
||||||
): List[(TournamentParticipant, TournamentParticipant)] =
|
|
||||||
val arr = players.toArray
|
|
||||||
resolveConflicts(arr, pastPairings)
|
|
||||||
arr.grouped(2).flatMap {
|
|
||||||
case Array(a, b) => Some(assignColors(a, b))
|
|
||||||
case _ => None
|
|
||||||
}.toList
|
|
||||||
|
|
||||||
private def resolveConflicts(arr: Array[TournamentParticipant], pastPairings: List[TournamentPairing]): Unit =
|
|
||||||
var i = 0
|
|
||||||
while i < arr.length - 1 do
|
|
||||||
if havePlayedBefore(arr(i), arr(i + 1), pastPairings) && i + 2 < arr.length then
|
|
||||||
val tmp = arr(i + 1)
|
|
||||||
arr(i + 1) = arr(i + 2)
|
|
||||||
arr(i + 2) = tmp
|
|
||||||
i += 2
|
|
||||||
|
|
||||||
private def havePlayedBefore(
|
|
||||||
a: TournamentParticipant,
|
|
||||||
b: TournamentParticipant,
|
|
||||||
pastPairings: List[TournamentPairing],
|
|
||||||
): Boolean =
|
|
||||||
pastPairings.exists(p =>
|
|
||||||
(p.whiteId == a.botId && p.blackId == b.botId) ||
|
|
||||||
(p.whiteId == b.botId && p.blackId == a.botId),
|
|
||||||
)
|
|
||||||
|
|
||||||
private def assignColors(
|
|
||||||
a: TournamentParticipant,
|
|
||||||
b: TournamentParticipant,
|
|
||||||
): (TournamentParticipant, TournamentParticipant) =
|
|
||||||
if ThreadLocalRandom.current().nextBoolean() then (a, b) else (b, a)
|
|
||||||
-284
@@ -1,284 +0,0 @@
|
|||||||
package de.nowchess.tournament.service
|
|
||||||
|
|
||||||
import de.nowchess.tournament.client.{CoreCreateGameRequest, CoreGameClient, CorePlayerInfo, CoreTimeControl}
|
|
||||||
import de.nowchess.tournament.domain.{Tournament, TournamentPairing, TournamentParticipant}
|
|
||||||
import de.nowchess.tournament.dto.{BotRef, Clock, CreateTournamentForm, PairingDto, ResultDto, Standing, TournamentDto, Variant}
|
|
||||||
import de.nowchess.tournament.error.TournamentError
|
|
||||||
import de.nowchess.tournament.repository.{PairingRepository, ParticipantRepository, TournamentRepository}
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import jakarta.inject.Inject
|
|
||||||
import jakarta.transaction.Transactional
|
|
||||||
import org.eclipse.microprofile.rest.client.inject.RestClient
|
|
||||||
import org.jboss.logging.Logger
|
|
||||||
import scala.compiletime.uninitialized
|
|
||||||
import scala.util.{Failure, Success, Try}
|
|
||||||
import java.time.Instant
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class TournamentService:
|
|
||||||
|
|
||||||
private val log = Logger.getLogger(classOf[TournamentService])
|
|
||||||
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
@Inject var tournamentRepository: TournamentRepository = uninitialized
|
|
||||||
@Inject var participantRepository: ParticipantRepository = uninitialized
|
|
||||||
@Inject var pairingRepository: PairingRepository = uninitialized
|
|
||||||
@Inject var streamManager: TournamentStreamManager = uninitialized
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
@RestClient
|
|
||||||
var coreGameClient: CoreGameClient = uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def create(createdBy: String, form: CreateTournamentForm): Tournament =
|
|
||||||
val t = new Tournament()
|
|
||||||
t.id = scala.util.Random.alphanumeric.take(6).mkString
|
|
||||||
t.fullName = form.name
|
|
||||||
t.nbRounds = form.nbRounds
|
|
||||||
t.clockLimit = form.clockLimit
|
|
||||||
t.clockIncrement = form.clockIncrement
|
|
||||||
t.rated = form.rated
|
|
||||||
t.status = "created"
|
|
||||||
t.currentRound = 0
|
|
||||||
t.createdBy = createdBy
|
|
||||||
tournamentRepository.persist(t)
|
|
||||||
t
|
|
||||||
|
|
||||||
def get(id: String): Option[Tournament] =
|
|
||||||
tournamentRepository.findOptById(id)
|
|
||||||
|
|
||||||
def list(): (List[Tournament], List[Tournament], List[Tournament]) =
|
|
||||||
(
|
|
||||||
tournamentRepository.findByStatus("created"),
|
|
||||||
tournamentRepository.findByStatus("started"),
|
|
||||||
tournamentRepository.findByStatus("finished"),
|
|
||||||
)
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def terminate(id: String, userId: String): Either[TournamentError, Unit] =
|
|
||||||
for
|
|
||||||
t <- tournamentRepository.findOptById(id).toRight(TournamentError.NotFound(id))
|
|
||||||
_ <- Either.cond(t.createdBy == userId, (), TournamentError.NotDirector)
|
|
||||||
_ <- Either.cond(t.status == "created", (), TournamentError.WrongStatus("created"))
|
|
||||||
yield
|
|
||||||
tournamentRepository.delete(t)
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def join(id: String, botId: String, botName: String): Either[TournamentError, Unit] =
|
|
||||||
for
|
|
||||||
t <- tournamentRepository.findOptById(id).toRight(TournamentError.NotFound(id))
|
|
||||||
_ <- Either.cond(t.status == "created", (), TournamentError.WrongStatus("created"))
|
|
||||||
_ <- Either.cond(
|
|
||||||
participantRepository.findByTournamentIdAndBotId(id, botId).isEmpty,
|
|
||||||
(),
|
|
||||||
TournamentError.AlreadyJoined,
|
|
||||||
)
|
|
||||||
yield
|
|
||||||
val p = new TournamentParticipant()
|
|
||||||
p.tournamentId = id
|
|
||||||
p.botId = botId
|
|
||||||
p.botName = botName
|
|
||||||
participantRepository.persist(p)
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def withdraw(id: String, botId: String): Either[TournamentError, Unit] =
|
|
||||||
for
|
|
||||||
t <- tournamentRepository.findOptById(id).toRight(TournamentError.NotFound(id))
|
|
||||||
_ <- Either.cond(t.status == "created", (), TournamentError.WrongStatus("created"))
|
|
||||||
p <- participantRepository.findByTournamentIdAndBotId(id, botId).toRight(TournamentError.NotJoined)
|
|
||||||
yield participantRepository.delete(p)
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def start(id: String, userId: String): Either[TournamentError, Tournament] =
|
|
||||||
for
|
|
||||||
t <- tournamentRepository.findOptById(id).toRight(TournamentError.NotFound(id))
|
|
||||||
_ <- Either.cond(t.createdBy == userId, (), TournamentError.NotDirector)
|
|
||||||
_ <- Either.cond(t.status == "created", (), TournamentError.WrongStatus("created"))
|
|
||||||
participants <- validateMinParticipants(id)
|
|
||||||
yield
|
|
||||||
t.status = "started"
|
|
||||||
t.currentRound = 1
|
|
||||||
t.startsAt = Instant.now()
|
|
||||||
tournamentRepository.persist(t)
|
|
||||||
streamManager.publish(t.id, """{"type":"tournamentStarted"}""")
|
|
||||||
startRound(t, 1, participants)
|
|
||||||
t
|
|
||||||
|
|
||||||
private def validateMinParticipants(id: String): Either[TournamentError, List[TournamentParticipant]] =
|
|
||||||
val ps = participantRepository.findByTournamentId(id)
|
|
||||||
Either.cond(ps.size >= 2, ps, TournamentError.NotEnoughParticipants)
|
|
||||||
|
|
||||||
private def startRound(t: Tournament, round: Int, participants: List[TournamentParticipant]): Unit =
|
|
||||||
val pastPairings = pairingRepository.findByTournamentId(t.id)
|
|
||||||
val (pairs, byeOpt) = SwissPairingService.computePairings(participants, pastPairings)
|
|
||||||
byeOpt.foreach(bye => createByePairing(t.id, round, bye))
|
|
||||||
pairs.foreach { case (white, black) => createRealPairing(t.id, round, white, black, t) }
|
|
||||||
streamManager.publish(t.id, s"""{"type":"roundStarted","round":$round}""")
|
|
||||||
|
|
||||||
private def createByePairing(tournamentId: String, round: Int, bye: TournamentParticipant): Unit =
|
|
||||||
val pairing = new TournamentPairing()
|
|
||||||
pairing.tournamentId = tournamentId
|
|
||||||
pairing.round = round
|
|
||||||
pairing.blackId = bye.botId
|
|
||||||
pairing.blackName = bye.botName
|
|
||||||
pairing.winner = "bye"
|
|
||||||
pairingRepository.persist(pairing)
|
|
||||||
bye.points += 0.5
|
|
||||||
bye.byeCount += 1
|
|
||||||
participantRepository.persist(bye)
|
|
||||||
|
|
||||||
private def createRealPairing(
|
|
||||||
tournamentId: String,
|
|
||||||
round: Int,
|
|
||||||
white: TournamentParticipant,
|
|
||||||
black: TournamentParticipant,
|
|
||||||
t: Tournament,
|
|
||||||
): Unit =
|
|
||||||
val tc = CoreTimeControl(Some(t.clockLimit), Some(t.clockIncrement), None)
|
|
||||||
val req = CoreCreateGameRequest(
|
|
||||||
Some(CorePlayerInfo(white.botId, white.botName)),
|
|
||||||
Some(CorePlayerInfo(black.botId, black.botName)),
|
|
||||||
Some(tc),
|
|
||||||
if t.rated then Some("Rated") else Some("Casual"),
|
|
||||||
)
|
|
||||||
Try(coreGameClient.createGame(req)) match
|
|
||||||
case Failure(ex) => log.errorf(ex, "Failed to create game for round %d in tournament %s", round, tournamentId)
|
|
||||||
case Success(resp) =>
|
|
||||||
val pairing = new TournamentPairing()
|
|
||||||
pairing.tournamentId = tournamentId
|
|
||||||
pairing.round = round
|
|
||||||
pairing.whiteId = white.botId
|
|
||||||
pairing.whiteName = white.botName
|
|
||||||
pairing.blackId = black.botId
|
|
||||||
pairing.blackName = black.botName
|
|
||||||
pairing.gameId = resp.gameId
|
|
||||||
pairingRepository.persist(pairing)
|
|
||||||
streamManager.publishToBot(tournamentId, white.botId, s"""{"type":"gameStart","round":$round,"gameId":"${resp.gameId}","color":"white"}""")
|
|
||||||
streamManager.publishToBot(tournamentId, black.botId, s"""{"type":"gameStart","round":$round,"gameId":"${resp.gameId}","color":"black"}""")
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
def handleGameResult(gameId: String, result: String, pgn: String): Unit =
|
|
||||||
pairingRepository.findByGameId(gameId).foreach { pairing =>
|
|
||||||
val (winnerStr, wPts, bPts) = parseResult(result)
|
|
||||||
pairing.winner = winnerStr
|
|
||||||
pairing.moveList = pgn
|
|
||||||
pairingRepository.persist(pairing)
|
|
||||||
updateParticipantStats(pairing, wPts, bPts)
|
|
||||||
checkRoundCompletion(pairing.tournamentId)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def parseResult(result: String): (String, Double, Double) = result match
|
|
||||||
case "1-0" => ("white", 1.0, 0.0)
|
|
||||||
case "0-1" => ("black", 0.0, 1.0)
|
|
||||||
case "1/2-1/2" => ("draw", 0.5, 0.5)
|
|
||||||
case _ => ("draw", 0.5, 0.5)
|
|
||||||
|
|
||||||
private def updateParticipantStats(pairing: TournamentPairing, wPts: Double, bPts: Double): Unit =
|
|
||||||
Option(pairing.whiteId).foreach { wId =>
|
|
||||||
participantRepository.findByTournamentIdAndBotId(pairing.tournamentId, wId).foreach { p =>
|
|
||||||
p.points += wPts
|
|
||||||
p.nbGames += 1
|
|
||||||
if wPts == 1.0 then p.wins += 1 else if wPts == 0.5 then p.draws += 1 else p.losses += 1
|
|
||||||
participantRepository.persist(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
participantRepository.findByTournamentIdAndBotId(pairing.tournamentId, pairing.blackId).foreach { p =>
|
|
||||||
p.points += bPts
|
|
||||||
p.nbGames += 1
|
|
||||||
if bPts == 1.0 then p.wins += 1 else if bPts == 0.5 then p.draws += 1 else p.losses += 1
|
|
||||||
participantRepository.persist(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def checkRoundCompletion(tournamentId: String): Unit =
|
|
||||||
tournamentRepository.findOptById(tournamentId).foreach { t =>
|
|
||||||
val roundPairings = pairingRepository.findByTournamentIdAndRound(tournamentId, t.currentRound)
|
|
||||||
val allDone = roundPairings.nonEmpty && roundPairings.forall(p => Option(p.winner).isDefined)
|
|
||||||
if allDone then onRoundComplete(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def onRoundComplete(t: Tournament): Unit =
|
|
||||||
streamManager.publish(t.id, s"""{"type":"roundFinished","round":${t.currentRound}}""")
|
|
||||||
recomputeBuchholz(t.id)
|
|
||||||
if t.currentRound >= t.nbRounds then finishTournament(t)
|
|
||||||
else
|
|
||||||
t.currentRound += 1
|
|
||||||
tournamentRepository.persist(t)
|
|
||||||
val participants = participantRepository.findByTournamentId(t.id)
|
|
||||||
startRound(t, t.currentRound, participants)
|
|
||||||
|
|
||||||
private def finishTournament(t: Tournament): Unit =
|
|
||||||
val participants = sortedStandings(participantRepository.findByTournamentId(t.id))
|
|
||||||
participants.headOption.foreach { winner =>
|
|
||||||
t.winnerId = winner.botId
|
|
||||||
t.winnerName = winner.botName
|
|
||||||
}
|
|
||||||
t.status = "finished"
|
|
||||||
tournamentRepository.persist(t)
|
|
||||||
val winnerInfo = participants.headOption
|
|
||||||
.map(w => s"""{"id":"${w.botId}","name":"${w.botName}"}""")
|
|
||||||
.getOrElse("null")
|
|
||||||
streamManager.publish(t.id, s"""{"type":"tournamentFinished","winner":$winnerInfo}""")
|
|
||||||
|
|
||||||
private def recomputeBuchholz(tournamentId: String): Unit =
|
|
||||||
val participants = participantRepository.findByTournamentId(tournamentId)
|
|
||||||
val pairings = pairingRepository.findByTournamentId(tournamentId)
|
|
||||||
val pointsById = participants.map(p => p.botId -> p.points).toMap
|
|
||||||
participants.foreach { p =>
|
|
||||||
val opponentIds = pairings.flatMap(pair =>
|
|
||||||
if pair.whiteId == p.botId then Some(pair.blackId)
|
|
||||||
else if pair.blackId == p.botId && Option(pair.whiteId).isDefined then Some(pair.whiteId)
|
|
||||||
else None,
|
|
||||||
)
|
|
||||||
p.tieBreak = opponentIds.flatMap(id => pointsById.get(id)).sum
|
|
||||||
participantRepository.persist(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getStandings(tournamentId: String): List[ResultDto] =
|
|
||||||
val participants = sortedStandings(participantRepository.findByTournamentId(tournamentId))
|
|
||||||
participants.zipWithIndex.map { case (p, idx) =>
|
|
||||||
ResultDto(idx + 1, p.points, p.tieBreak, BotRef(p.botId, p.botName), p.nbGames, p.wins, p.draws, p.losses)
|
|
||||||
}
|
|
||||||
|
|
||||||
def getPairings(tournamentId: String, round: Int): List[PairingDto] =
|
|
||||||
pairingRepository.findByTournamentIdAndRound(tournamentId, round).map(toPairingDto)
|
|
||||||
|
|
||||||
def getAllPairings(tournamentId: String): List[TournamentPairing] =
|
|
||||||
pairingRepository.findByTournamentId(tournamentId)
|
|
||||||
|
|
||||||
def getResults(tournamentId: String): List[ResultDto] = getStandings(tournamentId)
|
|
||||||
|
|
||||||
def toDto(t: Tournament, standings: List[ResultDto] = Nil): TournamentDto =
|
|
||||||
val participants = participantRepository.findByTournamentId(t.id)
|
|
||||||
TournamentDto(
|
|
||||||
id = t.id,
|
|
||||||
fullName = t.fullName,
|
|
||||||
clock = Clock(t.clockLimit, t.clockIncrement),
|
|
||||||
variant = Variant("standard", "Standard"),
|
|
||||||
rated = t.rated,
|
|
||||||
nbPlayers = participants.size,
|
|
||||||
nbRounds = t.nbRounds,
|
|
||||||
createdBy = t.createdBy,
|
|
||||||
startsAt = Option(t.startsAt).map(_.toString),
|
|
||||||
status = t.status,
|
|
||||||
round = t.currentRound,
|
|
||||||
standing = Standing(1, standings),
|
|
||||||
winner = if t.winnerId != null then Some(BotRef(t.winnerId, t.winnerName)) else None,
|
|
||||||
)
|
|
||||||
|
|
||||||
private def toPairingDto(p: TournamentPairing): PairingDto =
|
|
||||||
PairingDto(
|
|
||||||
id = p.id.toString,
|
|
||||||
round = p.round,
|
|
||||||
white = Option(p.whiteId).map(id => BotRef(id, p.whiteName)),
|
|
||||||
black = BotRef(p.blackId, p.blackName),
|
|
||||||
gameId = Option(p.gameId),
|
|
||||||
winner = Option(p.winner),
|
|
||||||
)
|
|
||||||
|
|
||||||
private def sortedStandings(participants: List[TournamentParticipant]): List[TournamentParticipant] =
|
|
||||||
participants.sortWith { (a, b) =>
|
|
||||||
if a.points != b.points then a.points > b.points
|
|
||||||
else if a.tieBreak != b.tieBreak then a.tieBreak > b.tieBreak
|
|
||||||
else a.botName < b.botName
|
|
||||||
}
|
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package de.nowchess.tournament.service
|
|
||||||
|
|
||||||
import io.smallrye.mutiny.subscription.MultiEmitter
|
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
|
||||||
import java.util.concurrent.{ConcurrentHashMap, CopyOnWriteArrayList}
|
|
||||||
import scala.jdk.CollectionConverters.*
|
|
||||||
|
|
||||||
@ApplicationScoped
|
|
||||||
class TournamentStreamManager:
|
|
||||||
|
|
||||||
private val tournamentEmitters = new ConcurrentHashMap[String, CopyOnWriteArrayList[MultiEmitter[? >: String]]]()
|
|
||||||
private val botEmitters = new ConcurrentHashMap[String, CopyOnWriteArrayList[MultiEmitter[? >: String]]]()
|
|
||||||
|
|
||||||
private def botKey(tournamentId: String, botId: String): String = s"${tournamentId}:${botId}"
|
|
||||||
|
|
||||||
def register(tournamentId: String, botId: String, emitter: MultiEmitter[? >: String]): Unit =
|
|
||||||
tournamentEmitters.computeIfAbsent(tournamentId, _ => new CopyOnWriteArrayList[MultiEmitter[? >: String]]()).add(emitter)
|
|
||||||
botEmitters.computeIfAbsent(botKey(tournamentId, botId), _ => new CopyOnWriteArrayList[MultiEmitter[? >: String]]()).add(emitter)
|
|
||||||
|
|
||||||
def unregister(tournamentId: String, botId: String, emitter: MultiEmitter[? >: String]): Unit =
|
|
||||||
Option(tournamentEmitters.get(tournamentId)).foreach(_.remove(emitter))
|
|
||||||
Option(botEmitters.get(botKey(tournamentId, botId))).foreach(_.remove(emitter))
|
|
||||||
|
|
||||||
def publish(tournamentId: String, eventJson: String): Unit =
|
|
||||||
Option(tournamentEmitters.get(tournamentId)).foreach { list =>
|
|
||||||
list.asScala.foreach(e => scala.util.Try(e.emit(eventJson)))
|
|
||||||
}
|
|
||||||
|
|
||||||
def publishToBot(tournamentId: String, botId: String, eventJson: String): Unit =
|
|
||||||
Option(botEmitters.get(botKey(tournamentId, botId))).foreach { list =>
|
|
||||||
list.asScala.foreach(e => scala.util.Try(e.emit(eventJson)))
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
quarkus:
|
|
||||||
http:
|
|
||||||
port: 8088
|
|
||||||
application:
|
|
||||||
name: nowchess-tournament
|
|
||||||
datasource:
|
|
||||||
db-kind: h2
|
|
||||||
username: sa
|
|
||||||
password: ""
|
|
||||||
jdbc:
|
|
||||||
url: "jdbc:h2:mem:nowchess-tournament;DB_CLOSE_DELAY=-1"
|
|
||||||
hibernate-orm:
|
|
||||||
schema-management:
|
|
||||||
strategy: drop-and-create
|
|
||||||
arc:
|
|
||||||
exclude-types: de.nowchess.tournament.redis.GameResultStreamListener
|
|
||||||
mp:
|
|
||||||
jwt:
|
|
||||||
verify:
|
|
||||||
publickey:
|
|
||||||
location: keys/test-public.pem
|
|
||||||
issuer: nowchess
|
|
||||||
smallrye:
|
|
||||||
jwt:
|
|
||||||
sign:
|
|
||||||
key:
|
|
||||||
location: keys/test-private.pem
|
|
||||||
nowchess:
|
|
||||||
internal:
|
|
||||||
secret: test-secret
|
|
||||||
auth:
|
|
||||||
enabled: false
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4zBHgRLMez2b6
|
|
||||||
wfdvvTJVR8xxbr/kJUMiq4ot14KhtTaGikFW+77ezjoqabFWH7CNjDvASWCM2n7X
|
|
||||||
PxL4fhUwzvTbhRZ2XNM80lKB+OIjP3hoNLvgeSNHbS4CztOfk2JVtQFLQdYJ/gvB
|
|
||||||
oFPgBtZYO/SZVML28d5U92JrWRIC1e1Ht1oKwKJoOqtTJrs/RuOlKQ/du4kwY8m0
|
|
||||||
jPw05wFA1YRMUC78xKklCVYCufYewIUTdKxATK0ZKWBoPCJnxDg8gwgpnV1wHQrH
|
|
||||||
GcbZvhcVg3GWpDcYdnogV4rlssws57+uAhGRyQBkmmhVb+zT+LT7WXDPB46MnHkK
|
|
||||||
FIZaxEkHAgMBAAECggEAAvu4Zih1w8+RWAb9mZ4yS9Im6MXi7yny1YJzbp4GC9pD
|
|
||||||
ERT2TRMvV6V4puqh5EQKs55J8Ka+mkeEuLDZ+4z9hpYwucKCRFLnThoPHu4HqI4D
|
|
||||||
wZroVY1fFm4aygzQucjFU6DibnaXn/2r7upJsFor56zAHCGULCxnbHO58QW1Frqa
|
|
||||||
UrTndSkrxavBD9LL1ohPEy3saXlRCVAEM5l7jZbg52dPauIYAOv0e+EE3RETw/Xz
|
|
||||||
3EWukIZ7PKyoyuQm8Sv2u7lyISljDGlvrW5IjVRPMPqOKNOa/pV3qU4mbUY6GjbC
|
|
||||||
B4xt8kEKjVSkTeMXA+W0gnZddnQOtcQYSrYWWes+AQKBgQDzjmt1ZJktZG96M8+f
|
|
||||||
Ov9JznfzSLYxN7EboDhqjTVBOkb6flRSYrd9E6gReIIrq5Sjs9Z+toA/u8BmjQ/P
|
|
||||||
GTrrLVh6bLBicUGKcmQFKw/0D9lOlbxaMg8VO9rqSb/AslumJwjucU7DA+WAN52j
|
|
||||||
cyiLiw+EmWjL/DV51fHHI18SgQKBgQDCPRzpeP8Qox83/+tGR/6fSSRi5ec3ZVPy
|
|
||||||
aCCCZM6qqhLv3hJkV0djRruVVfe136PwUi20BW6aF0PXmxDIGRWqDLQGkvDNEhjw
|
|
||||||
ZLBv/dYtW2HBZhq4E0w8DiaNZCOWvpLQ3QCEtzmuhyHhNqYHzvmuerk+w4c/8fY6
|
|
||||||
DFyPyiAHhwKBgDrpO/zNNG/SV1SLq7CsKIvFsSXbdJY7Dk/MVVkQhs0cN4bnf6Xd
|
|
||||||
0twiIQj4ySOfAPkHyt4jbqn70/H6NNS3GZVBBqG2IIPvORcvzBmj7Nvv6XQkq8Z1
|
|
||||||
TUipja4V4JfPjHOIBZUHOzHYg26cBTk/5ZK7NCmyobKVcqnhofW1DI4BAoGAaRu4
|
|
||||||
8X5QSCh9VEhggH+lAX0K+5l9LTTf4GUIcocqbp/p73M0cKfqMYatK3qBuSF0DS/r
|
|
||||||
G2d1Gl1MkPeQdTddyc9l+8i4FcCdTjiuYWvy4kh49bbS7plCv5zIr+pod8JYoD13
|
|
||||||
clnUFOV7J+vynHccFZbDd3tHTQsaOv9Fd2nhOzECgYEA8SWBEmTuaBh+0vr6zS+E
|
|
||||||
wD+cwB3iaGo+7fP7TZ+v1kxoDlcDjPYM4ikiOB+OPGNkAfqc3MGsbhfgcxqD0+5r
|
|
||||||
kpCFyiyieyoT+7hkMpMsJCNwFO+29fc3DDqPX4Keqp26tMxtRzYea3GtVShiRXew
|
|
||||||
5i4ReFwm3/IWDn9kLmHT6Fg=
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuMwR4ESzHs9m+sH3b70y
|
|
||||||
VUfMcW6/5CVDIquKLdeCobU2hopBVvu+3s46KmmxVh+wjYw7wElgjNp+1z8S+H4V
|
|
||||||
MM7024UWdlzTPNJSgfjiIz94aDS74HkjR20uAs7Tn5NiVbUBS0HWCf4LwaBT4AbW
|
|
||||||
WDv0mVTC9vHeVPdia1kSAtXtR7daCsCiaDqrUya7P0bjpSkP3buJMGPJtIz8NOcB
|
|
||||||
QNWETFAu/MSpJQlWArn2HsCFE3SsQEytGSlgaDwiZ8Q4PIMIKZ1dcB0KxxnG2b4X
|
|
||||||
FYNxlqQ3GHZ6IFeK5bLMLOe/rgIRkckAZJpoVW/s0/i0+1lwzweOjJx5ChSGWsRJ
|
|
||||||
BwIDAQAB
|
|
||||||
-----END PUBLIC KEY-----
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package de.nowchess.tournament.resource
|
|
||||||
|
|
||||||
import io.quarkus.test.junit.QuarkusTestProfile
|
|
||||||
import java.util.Map as JMap
|
|
||||||
|
|
||||||
class H2TestProfile extends QuarkusTestProfile:
|
|
||||||
|
|
||||||
override def getConfigOverrides(): JMap[String, String] =
|
|
||||||
JMap.of(
|
|
||||||
"quarkus.datasource.db-kind", "h2",
|
|
||||||
"quarkus.datasource.jdbc.url", "jdbc:h2:mem:nowchess-tournament;DB_CLOSE_DELAY=-1",
|
|
||||||
"quarkus.datasource.username", "sa",
|
|
||||||
"quarkus.datasource.password", "",
|
|
||||||
"quarkus.hibernate-orm.schema-management.strategy", "drop-and-create",
|
|
||||||
)
|
|
||||||
-233
@@ -1,233 +0,0 @@
|
|||||||
package de.nowchess.tournament.resource
|
|
||||||
|
|
||||||
import de.nowchess.tournament.client.{CoreGameClient, CoreGameResponse}
|
|
||||||
import io.quarkus.test.InjectMock
|
|
||||||
import io.quarkus.test.junit.QuarkusTest
|
|
||||||
import io.restassured.RestAssured
|
|
||||||
import io.restassured.http.ContentType
|
|
||||||
import io.restassured.response.ValidatableResponse
|
|
||||||
import io.smallrye.jwt.build.Jwt
|
|
||||||
import org.eclipse.microprofile.rest.client.inject.RestClient
|
|
||||||
import org.hamcrest.Matchers.*
|
|
||||||
import org.junit.jupiter.api.{BeforeEach, Test}
|
|
||||||
import org.mockito.{ArgumentMatchers, Mockito}
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
class TournamentResourceTest:
|
|
||||||
|
|
||||||
@InjectMock
|
|
||||||
@RestClient
|
|
||||||
// scalafix:off DisableSyntax.var
|
|
||||||
var coreGameClient: CoreGameClient = scala.compiletime.uninitialized
|
|
||||||
// scalafix:on
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
def setup(): Unit =
|
|
||||||
Mockito.when(coreGameClient.createGame(ArgumentMatchers.any())).thenReturn(CoreGameResponse("game-test-123"))
|
|
||||||
|
|
||||||
private def g() = RestAssured.`given`().contentType(ContentType.JSON)
|
|
||||||
|
|
||||||
private def directorToken(userId: String = "director-1"): String =
|
|
||||||
Jwt.issuer("nowchess").subject(userId).expiresIn(3600).sign()
|
|
||||||
|
|
||||||
private def botToken(botId: String, botName: String): String =
|
|
||||||
Jwt.issuer("nowchess").subject(botId).claim("type", "bot").claim("name", botName).expiresIn(3600).sign()
|
|
||||||
|
|
||||||
private def authed(token: String) =
|
|
||||||
g().header("Authorization", s"Bearer $token")
|
|
||||||
|
|
||||||
private def formAuthed(token: String) =
|
|
||||||
RestAssured.`given`().contentType(ContentType.URLENC).header("Authorization", s"Bearer $token")
|
|
||||||
|
|
||||||
private def createTournament(token: String, name: String = "Test Tour", nbRounds: Int = 3): String =
|
|
||||||
formAuthed(token)
|
|
||||||
.formParam("name", name)
|
|
||||||
.formParam("nbRounds", nbRounds)
|
|
||||||
.formParam("clockLimit", 300)
|
|
||||||
.formParam("clockIncrement", 5)
|
|
||||||
.formParam("rated", true)
|
|
||||||
.when().post("/api/tournament")
|
|
||||||
.`then`().statusCode(201).extract().path[String]("id")
|
|
||||||
|
|
||||||
private def postAndCheck(token: String, path: String, expectedStatus: Int): ValidatableResponse =
|
|
||||||
authed(token).when().post(path).`then`().statusCode(expectedStatus)
|
|
||||||
|
|
||||||
private def deleteAndCheck(token: String, path: String, expectedStatus: Int): ValidatableResponse =
|
|
||||||
authed(token).when().delete(path).`then`().statusCode(expectedStatus)
|
|
||||||
|
|
||||||
private def botJoin(tournamentId: String, botId: String, botName: String): ValidatableResponse =
|
|
||||||
val bt = botToken(botId, botName)
|
|
||||||
authed(bt).when().post(s"/api/tournament/$tournamentId/join").`then`().statusCode(200)
|
|
||||||
|
|
||||||
private def startTournament(token: String, tournamentId: String): ValidatableResponse =
|
|
||||||
authed(token).when().post(s"/api/tournament/$tournamentId/start").`then`().statusCode(200)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def createsTournamentWhenAuthenticated(): Unit =
|
|
||||||
formAuthed(directorToken())
|
|
||||||
.formParam("name", "Test Tour")
|
|
||||||
.formParam("nbRounds", 3)
|
|
||||||
.formParam("clockLimit", 300)
|
|
||||||
.formParam("clockIncrement", 5)
|
|
||||||
.formParam("rated", true)
|
|
||||||
.when().post("/api/tournament")
|
|
||||||
.`then`().statusCode(201)
|
|
||||||
.body("fullName", is("Test Tour"))
|
|
||||||
.body("status", is("created"))
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returns401WhenUnauthenticated(): Unit =
|
|
||||||
RestAssured.`given`().contentType(ContentType.URLENC)
|
|
||||||
.formParam("name", "Test Tour")
|
|
||||||
.formParam("nbRounds", 3)
|
|
||||||
.formParam("clockLimit", 300)
|
|
||||||
.formParam("clockIncrement", 5)
|
|
||||||
.when().post("/api/tournament")
|
|
||||||
.`then`().statusCode(401)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsEmptyListsOnFreshStart(): Unit =
|
|
||||||
RestAssured.`given`().when().get("/api/tournament")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.body("created", notNullValue())
|
|
||||||
.body("started", notNullValue())
|
|
||||||
.body("finished", notNullValue())
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsCreatedTournamentInCreatedList(): Unit =
|
|
||||||
val id = createTournament(directorToken("director-list"), "ListTour")
|
|
||||||
RestAssured.`given`().when().get("/api/tournament")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.body("created.id", hasItem(id))
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returns404ForUnknownId(): Unit =
|
|
||||||
RestAssured.`given`().when().get("/api/tournament/XXXXXX").`then`().statusCode(404)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsTournamentWithStandings(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-get"), "GetTour")
|
|
||||||
RestAssured.`given`().when().get(s"/api/tournament/$id")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.body("id", is(id))
|
|
||||||
.body("standing", notNullValue())
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def directorCanTerminateCreatedTournament(): Unit =
|
|
||||||
val token = directorToken("dir-term")
|
|
||||||
val id = createTournament(token, "TermTour")
|
|
||||||
deleteAndCheck(token, s"/api/tournament/$id", 204)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def nonDirectorGets403OnTerminate(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-403"), "SecureTour")
|
|
||||||
deleteAndCheck(directorToken("other-user-403"), s"/api/tournament/$id", 403)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def cannotTerminateStartedTournament(): Unit =
|
|
||||||
val token = directorToken("dir-started")
|
|
||||||
val id = createTournament(token, "StartedTour")
|
|
||||||
botJoin(id, "sbot-1", "StartBot1")
|
|
||||||
botJoin(id, "sbot-2", "StartBot2")
|
|
||||||
startTournament(token, id)
|
|
||||||
deleteAndCheck(token, s"/api/tournament/$id", 409)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def botJoinsSuccessfully(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-join"), "JoinTour")
|
|
||||||
authed(botToken("joinbot-1", "JoinBot1"))
|
|
||||||
.when().post(s"/api/tournament/$id/join")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.body("ok", is(true))
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def nonBotTokenReturns403OnJoin(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-nbjoin"), "NbJoinTour")
|
|
||||||
postAndCheck(directorToken("regular-user"), s"/api/tournament/$id/join", 403)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def alreadyJoinedReturns409(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-dbl"), "DblJoinTour")
|
|
||||||
val bt = botToken("dblbot-1", "DblBot1")
|
|
||||||
botJoin(id, "dblbot-1", "DblBot1")
|
|
||||||
authed(bt).when().post(s"/api/tournament/$id/join").`then`().statusCode(409)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def startedTournamentReturns409OnJoin(): Unit =
|
|
||||||
val token = directorToken("dir-sjoin")
|
|
||||||
val id = createTournament(token, "SjoinTour")
|
|
||||||
botJoin(id, "sjbot-1", "SjBot1")
|
|
||||||
botJoin(id, "sjbot-2", "SjBot2")
|
|
||||||
startTournament(token, id)
|
|
||||||
authed(botToken("sjbot-3", "SjBot3")).when().post(s"/api/tournament/$id/join").`then`().statusCode(409)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def joinedBotCanWithdraw(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-wd"), "WdTour")
|
|
||||||
val bt = botToken("wdbot-1", "WdBot1")
|
|
||||||
botJoin(id, "wdbot-1", "WdBot1")
|
|
||||||
authed(bt).when().post(s"/api/tournament/$id/withdraw")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.body("ok", is(true))
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def notJoinedBotReturns409OnWithdraw(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-wdnj"), "WdnjTour")
|
|
||||||
val bt = botToken("wdnjbot-1", "WdnjBot1")
|
|
||||||
authed(bt).when().post(s"/api/tournament/$id/withdraw").`then`().statusCode(409)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def directorStartsWith2Bots(): Unit =
|
|
||||||
val token = directorToken("dir-start")
|
|
||||||
val id = createTournament(token, "StartTour2")
|
|
||||||
botJoin(id, "stbot-1", "StBot1")
|
|
||||||
botJoin(id, "stbot-2", "StBot2")
|
|
||||||
postAndCheck(token, s"/api/tournament/$id/start", 200)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def nonDirectorReturns403OnStart(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-ndstart"), "NdStartTour")
|
|
||||||
botJoin(id, "ndstbot-1", "NdstBot1")
|
|
||||||
botJoin(id, "ndstbot-2", "NdstBot2")
|
|
||||||
postAndCheck(directorToken("other-ndstart"), s"/api/tournament/$id/start", 403)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def fewerThan2BotsReturns409OnStart(): Unit =
|
|
||||||
val token = directorToken("dir-1bot")
|
|
||||||
val id = createTournament(token, "1BotTour")
|
|
||||||
botJoin(id, "onebot-1", "OneBot1")
|
|
||||||
postAndCheck(token, s"/api/tournament/$id/start", 409)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def resultsReturns200WithNdjsonContentType(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-res"), "ResTour")
|
|
||||||
RestAssured.`given`().when().get(s"/api/tournament/$id/results")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.contentType("application/x-ndjson")
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsPairingsForRoundAfterStart(): Unit =
|
|
||||||
val token = directorToken("dir-round")
|
|
||||||
val id = createTournament(token, "RoundTour")
|
|
||||||
botJoin(id, "rndbot-1", "RndBot1")
|
|
||||||
botJoin(id, "rndbot-2", "RndBot2")
|
|
||||||
startTournament(token, id)
|
|
||||||
RestAssured.`given`().when().get(s"/api/tournament/$id/round/1").`then`().statusCode(200)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returns404ForUnknownTournamentRound(): Unit =
|
|
||||||
RestAssured.`given`().when().get("/api/tournament/XXXXXX/round/1").`then`().statusCode(404)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsPgnByDefault(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-pgn"), "PgnTour")
|
|
||||||
RestAssured.`given`().when().get(s"/api/tournament/$id/export/games").`then`().statusCode(200)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def returnsNdjsonWhenAcceptApplicationXNdjson(): Unit =
|
|
||||||
val id = createTournament(directorToken("dir-ndjson"), "NdjsonTour")
|
|
||||||
RestAssured.`given`()
|
|
||||||
.header("Accept", "application/x-ndjson")
|
|
||||||
.when().get(s"/api/tournament/$id/export/games")
|
|
||||||
.`then`().statusCode(200)
|
|
||||||
.contentType("application/x-ndjson")
|
|
||||||
-73
@@ -1,73 +0,0 @@
|
|||||||
package de.nowchess.tournament.service
|
|
||||||
|
|
||||||
import de.nowchess.tournament.domain.{TournamentPairing, TournamentParticipant}
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.jupiter.api.Assertions.*
|
|
||||||
|
|
||||||
class SwissPairingServiceTest:
|
|
||||||
|
|
||||||
private def makeParticipant(botId: String, botName: String, points: Double = 0.0, byeCount: Int = 0): TournamentParticipant =
|
|
||||||
val p = new TournamentParticipant()
|
|
||||||
p.botId = botId
|
|
||||||
p.botName = botName
|
|
||||||
p.points = points
|
|
||||||
p.byeCount = byeCount
|
|
||||||
p
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def pairs2PlayersRandomlyAssignsColors(): Unit =
|
|
||||||
val p1 = makeParticipant("b1", "BotOne")
|
|
||||||
val p2 = makeParticipant("b2", "BotTwo")
|
|
||||||
val (pairs, bye) = SwissPairingService.computePairings(List(p1, p2), Nil)
|
|
||||||
assertEquals(1, pairs.size)
|
|
||||||
assertTrue(bye.isEmpty)
|
|
||||||
val (white, black) = pairs.head
|
|
||||||
val ids = Set(white.botId, black.botId)
|
|
||||||
assertEquals(Set("b1", "b2"), ids)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def pairs4PlayersTopVsEachOther(): Unit =
|
|
||||||
val p1 = makeParticipant("b1", "A", points = 2.0)
|
|
||||||
val p2 = makeParticipant("b2", "B", points = 1.5)
|
|
||||||
val p3 = makeParticipant("b3", "C", points = 1.0)
|
|
||||||
val p4 = makeParticipant("b4", "D", points = 0.0)
|
|
||||||
val (pairs, bye) = SwissPairingService.computePairings(List(p1, p2, p3, p4), Nil)
|
|
||||||
assertEquals(2, pairs.size)
|
|
||||||
assertTrue(bye.isEmpty)
|
|
||||||
val pair1Ids = Set(pairs(0)._1.botId, pairs(0)._2.botId)
|
|
||||||
val pair2Ids = Set(pairs(1)._1.botId, pairs(1)._2.botId)
|
|
||||||
assertEquals(Set("b1", "b2"), pair1Ids)
|
|
||||||
assertEquals(Set("b3", "b4"), pair2Ids)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def oddCountLowestRankedGetsBye(): Unit =
|
|
||||||
val p1 = makeParticipant("b1", "A", points = 2.0)
|
|
||||||
val p2 = makeParticipant("b2", "B", points = 1.0)
|
|
||||||
val p3 = makeParticipant("b3", "C", points = 0.0)
|
|
||||||
val (pairs, bye) = SwissPairingService.computePairings(List(p1, p2, p3), Nil)
|
|
||||||
assertEquals(1, pairs.size)
|
|
||||||
assertTrue(bye.isDefined)
|
|
||||||
assertEquals("b3", bye.get.botId)
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def avoidsRematchSwapsWhenPairAlreadyPlayed(): Unit =
|
|
||||||
val p1 = makeParticipant("b1", "A", points = 2.0)
|
|
||||||
val p2 = makeParticipant("b2", "B", points = 1.5)
|
|
||||||
val p3 = makeParticipant("b3", "C", points = 1.5)
|
|
||||||
val p4 = makeParticipant("b4", "D", points = 0.0)
|
|
||||||
val pastPairing = new TournamentPairing()
|
|
||||||
pastPairing.whiteId = "b1"
|
|
||||||
pastPairing.blackId = "b2"
|
|
||||||
val (pairs, _) = SwissPairingService.computePairings(List(p1, p2, p3, p4), List(pastPairing))
|
|
||||||
val pair1Ids = Set(pairs(0)._1.botId, pairs(0)._2.botId)
|
|
||||||
assertFalse(pair1Ids == Set("b1", "b2"), "b1 and b2 should not be paired again")
|
|
||||||
|
|
||||||
@Test
|
|
||||||
def playerWithFewerByesGetsTheByeFirst(): Unit =
|
|
||||||
val p1 = makeParticipant("b1", "A", points = 1.0, byeCount = 1)
|
|
||||||
val p2 = makeParticipant("b2", "B", points = 0.5, byeCount = 0)
|
|
||||||
val p3 = makeParticipant("b3", "C", points = 0.0, byeCount = 0)
|
|
||||||
val (pairs, bye) = SwissPairingService.computePairings(List(p1, p2, p3), Nil)
|
|
||||||
assertEquals(1, pairs.size)
|
|
||||||
assertTrue(bye.isDefined)
|
|
||||||
assertEquals("b3", bye.get.botId)
|
|
||||||
@@ -178,29 +178,3 @@
|
|||||||
### 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,6 +29,8 @@ 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=14
|
MINOR=13
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -26,5 +26,4 @@ include(
|
|||||||
"modules:ws",
|
"modules:ws",
|
||||||
"modules:store",
|
"modules:store",
|
||||||
"modules:coordinator",
|
"modules:coordinator",
|
||||||
"modules:tournament",
|
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user