Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a91ba5da9a | |||
| f079f42d28 | |||
| be941ff414 | |||
| 36a0b26c65 | |||
| f2d79e4952 | |||
| fba324a5b0 | |||
| 7bf91b2280 | |||
| 343e2bdd10 | |||
| 751a58b606 | |||
| 30295a4bb9 | |||
| f44d3ee376 | |||
| 688d30e2b1 | |||
| 98c64fc0d5 |
@@ -127,7 +127,7 @@ jobs:
|
|||||||
if [ -n "$MARCH" ]; then
|
if [ -n "$MARCH" ]; then
|
||||||
MARCH_ARG="-Dquarkus.native.additional-build-args=$MARCH"
|
MARCH_ARG="-Dquarkus.native.additional-build-args=$MARCH"
|
||||||
fi
|
fi
|
||||||
./gradlew :modules:${{ matrix.module }}:build -x test -Dquarkus.native.enabled=true -Dquarkus.package.jar.enabled=false -Dquarkus.profile=deployed $MARCH_ARG --no-daemon
|
./gradlew :modules:${{ matrix.module }}:build -x test -x spotlessScalaCheck -x checkScalafix -Dquarkus.native.enabled=true -Dquarkus.package.jar.enabled=false -Dquarkus.profile=deployed $MARCH_ARG --no-daemon
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
if: steps.image-check.outputs.exists == 'false'
|
if: steps.image-check.outputs.exists == 'false'
|
||||||
|
|||||||
@@ -569,3 +569,44 @@
|
|||||||
|
|
||||||
* 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-06-17)
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
* **api:** define shared EventEnvelope and EventType for Redis EventBus ([#61](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/61)) ([595c172](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/595c172900da99de367c274488c3ccbeaef55882))
|
||||||
|
* **bot-platform:** migrate BotRegistry to Redis Streams consumer group ([#63](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/63)) ([0ad2e10](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0ad2e10999213df6dd00f0c31a088c28a4dc0083))
|
||||||
|
* **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))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* **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))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **reflection:** add native reflection configuration for tournament classes ([65bc6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/65bc6a759937543df2d29905688bfa9e68d0c9d4))
|
||||||
|
* 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))
|
||||||
|
* **ws:** migrate challenge notifications to Redis Streams ([#66](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/66)) ([55f102c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/55f102cbaa684be94a158b16aaa42a50b36afaf3))
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
* enable official bots to connect to external tournament server ([#71](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/71)) ([688d30e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/688d30e2b10026923372be5fca3c63eaaee2de2a))
|
||||||
|
* 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))
|
||||||
|
* **official-bots:** NCS-70-auto-register official bots with account service ([#59](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/59)) ([7117a93](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7117a93376272094d0b1a6abf2121254ce396684))
|
||||||
|
* 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))
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ class AccountService:
|
|||||||
.subject(botId.toString)
|
.subject(botId.toString)
|
||||||
.expiresAt(Long.MaxValue)
|
.expiresAt(Long.MaxValue)
|
||||||
.claim("type", "bot")
|
.claim("type", "bot")
|
||||||
|
.claim("isBot", true)
|
||||||
.claim("name", botName)
|
.claim("name", botName)
|
||||||
.sign()
|
.sign()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=24
|
MINOR=25
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -10,3 +10,29 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **analytics:** upgrade Spark to 4.0.3 — 3.5.x has no official Docker image ([46af115](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/46af1154de34a8596cb6cb28c6fad7aba90f597c))
|
* **analytics:** upgrade Spark to 4.0.3 — 3.5.x has no official Docker image ([46af115](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/46af1154de34a8596cb6cb28c6fad7aba90f597c))
|
||||||
|
## (2026-06-19)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **analytics:** add Dockerfile, CI workflow, and stable jar name for K8s deployment ([95215b6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/95215b6a420fd526df1aa395f9b087556c8ad03b))
|
||||||
|
* **analytics:** add PostgreSQL JDBC write-back to all four batch jobs ([0e0ea4c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0e0ea4c9893c6efed52e633e55d05ab3ed004502))
|
||||||
|
* **analytics:** add Spark batch analytics module ([259b3bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/259b3bbb24c0f23326269b93f4b3c84012f727cd))
|
||||||
|
* **analytics:** add Structured Streaming, MLlib clustering, GraphX jobs ([e1d80b9](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e1d80b9331666feea191b1fd08aa762f3581c918))
|
||||||
|
* **official-bots:** park expert bot on tournament server at startup ([#76](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/76)) ([751a58b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/751a58b6061f7434115e229a7661894c76768bc2))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **analytics:** upgrade Spark to 4.0.3 — 3.5.x has no official Docker image ([46af115](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/46af1154de34a8596cb6cb28c6fad7aba90f597c))
|
||||||
|
## (2026-06-21)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **analytics:** add Dockerfile, CI workflow, and stable jar name for K8s deployment ([95215b6](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/95215b6a420fd526df1aa395f9b087556c8ad03b))
|
||||||
|
* **analytics:** add PostgreSQL JDBC write-back to all four batch jobs ([0e0ea4c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/0e0ea4c9893c6efed52e633e55d05ab3ed004502))
|
||||||
|
* **analytics:** add Spark batch analytics module ([259b3bb](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/259b3bbb24c0f23326269b93f4b3c84012f727cd))
|
||||||
|
* **analytics:** add Structured Streaming, MLlib clustering, GraphX jobs ([e1d80b9](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e1d80b9331666feea191b1fd08aa762f3581c918))
|
||||||
|
* **official-bots:** park expert bot on tournament server at startup ([#76](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/76)) ([751a58b](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/751a58b6061f7434115e229a7661894c76768bc2))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **analytics:** upgrade Spark to 4.0.3 — 3.5.x has no official Docker image ([46af115](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/46af1154de34a8596cb6cb28c6fad7aba90f597c))
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
// NOWCHESS_JDBC_URL (default: jdbc:postgresql://localhost:5432/nowchess)
|
// NOWCHESS_JDBC_URL (default: jdbc:postgresql://localhost:5432/nowchess)
|
||||||
// NOWCHESS_DB_USER (default: nowchess)
|
// NOWCHESS_DB_USER (default: nowchess)
|
||||||
// NOWCHESS_DB_PASS (default: nowchess)
|
// NOWCHESS_DB_PASS (default: nowchess)
|
||||||
|
// NOWCHESS_PGN_PATH (optional) — file or http(s) URL of a Lichess PGN dump (.pgn or .pgn.zst).
|
||||||
|
// When set, all batch jobs read games from the dump instead of PostgreSQL and
|
||||||
|
// skip JDBC write-back (Parquet/CSV output only). Demo data source.
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("scala")
|
id("scala")
|
||||||
@@ -71,6 +74,10 @@ dependencies {
|
|||||||
|
|
||||||
// PostgreSQL JDBC driver bundled so it is available on executor classpath.
|
// PostgreSQL JDBC driver bundled so it is available on executor classpath.
|
||||||
implementation("org.postgresql:postgresql:42.7.4")
|
implementation("org.postgresql:postgresql:42.7.4")
|
||||||
|
|
||||||
|
// zstd-jni: decompress Lichess .pgn.zst dumps in-process. Provided at runtime by Spark
|
||||||
|
// (it uses zstd-jni internally for shuffle/event-log compression), so compile-only here.
|
||||||
|
compileOnly("com.github.luben:zstd-jni:1.5.6-9")
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package de.nowchess.analytics
|
||||||
|
|
||||||
|
import org.apache.spark.SparkFiles
|
||||||
|
import org.apache.spark.sql.DataFrame
|
||||||
|
import org.apache.spark.sql.SparkSession
|
||||||
|
import org.apache.spark.sql.functions as F
|
||||||
|
|
||||||
|
/** Normalised game-record source for the batch jobs.
|
||||||
|
*
|
||||||
|
* Every batch job consumes the same five-column shape:
|
||||||
|
* - white_id, black_id : player identifiers
|
||||||
|
* - result : one of "white", "black", "draw"
|
||||||
|
* - move_count : number of plies
|
||||||
|
* - pgn : full PGN ("[Event …]…\n\n1. e4 …"), header and movetext separated by a blank line
|
||||||
|
*
|
||||||
|
* Two backends, selected by the `NOWCHESS_PGN_PATH` environment variable:
|
||||||
|
* - unset → PostgreSQL `game_records` table (production)
|
||||||
|
* - set → a Lichess PGN dump file/URL (demo). Point it at a `lichess_db_standard_rated_*.pgn[.zst]` to drive every
|
||||||
|
* batch job from real Lichess games.
|
||||||
|
*
|
||||||
|
* Lichess parsing uses only Spark SQL string functions — no UDFs — so Catalyst can push predicates, matching the
|
||||||
|
* no-UDF approach already used in OpeningBookJob.
|
||||||
|
*/
|
||||||
|
object GameSource:
|
||||||
|
|
||||||
|
private val PgnPathEnv = "NOWCHESS_PGN_PATH"
|
||||||
|
|
||||||
|
/** True when a Lichess PGN dump is configured; jobs use this to skip JDBC write-back. */
|
||||||
|
def isPgnMode: Boolean = sys.env.contains(PgnPathEnv)
|
||||||
|
|
||||||
|
def load(spark: SparkSession, jdbcUrl: String, dbUser: String, dbPass: String): DataFrame =
|
||||||
|
sys.env.get(PgnPathEnv) match
|
||||||
|
case Some(path) => fromLichessPgn(spark, path)
|
||||||
|
case None => fromJdbc(spark, jdbcUrl, dbUser, dbPass)
|
||||||
|
|
||||||
|
def fromJdbc(spark: SparkSession, jdbcUrl: String, dbUser: String, dbPass: String): DataFrame =
|
||||||
|
spark.read
|
||||||
|
.format("jdbc")
|
||||||
|
.option("url", jdbcUrl)
|
||||||
|
.option("dbtable", "game_records")
|
||||||
|
.option("user", dbUser)
|
||||||
|
.option("password", dbPass)
|
||||||
|
.option("driver", "org.postgresql.Driver")
|
||||||
|
.option("fetchsize", "10000")
|
||||||
|
.load()
|
||||||
|
.select("white_id", "black_id", "result", "move_count", "pgn")
|
||||||
|
|
||||||
|
/** Parses a Lichess PGN dump into the normalised game shape.
|
||||||
|
*
|
||||||
|
* `path` may be:
|
||||||
|
* - an http(s)/ftp URL — fetched once via SparkContext.addFile and distributed to executors, then read from the
|
||||||
|
* local replica (no S3/PVC needed; handy for a staging demo)
|
||||||
|
* - any Hadoop-readable path (file://, hdfs://, s3a://, …)
|
||||||
|
*
|
||||||
|
* `.zst` dumps (Lichess' native format) are decompressed in-process via zstd-jni; `.gz`/`.bz2` are handled by
|
||||||
|
* Spark's text reader codecs.
|
||||||
|
*
|
||||||
|
* Records are split on the "[Event " tag that opens every game, so each row holds one complete game (the empty
|
||||||
|
* fragment before the first game is filtered out). Header tags are read with regexp_extract; the movetext (after the
|
||||||
|
* blank line) is cleaned of clock/eval comments and move numbers to count plies.
|
||||||
|
*/
|
||||||
|
def fromLichessPgn(spark: SparkSession, path: String): DataFrame =
|
||||||
|
val resolved = resolvePath(spark, path)
|
||||||
|
val record = F.col("value")
|
||||||
|
|
||||||
|
val resultTag = F.regexp_extract(record, "Result \"([^\"]*)\"", 1)
|
||||||
|
val result = F
|
||||||
|
.when(resultTag === "1-0", "white")
|
||||||
|
.when(resultTag === "0-1", "black")
|
||||||
|
.when(resultTag === "1/2-1/2", "draw")
|
||||||
|
.otherwise(F.lit(null).cast("string"))
|
||||||
|
|
||||||
|
val moveText = F.coalesce(F.split(record, "\n\n").getItem(1), F.lit(""))
|
||||||
|
val noComment = F.regexp_replace(moveText, "\\{[^}]*\\}", "")
|
||||||
|
val noResult = F.regexp_replace(noComment, "(1-0|0-1|1/2-1/2|\\*)", "")
|
||||||
|
val noNumbers = F.regexp_replace(noResult, "\\d+\\.+", " ")
|
||||||
|
val plies = F.size(F.filter(F.split(F.trim(noNumbers), "\\s+"), tok => F.length(tok) > 0))
|
||||||
|
|
||||||
|
spark.read
|
||||||
|
.option("lineSep", "[Event ")
|
||||||
|
.text(resolved)
|
||||||
|
.filter(F.length(F.trim(record)) > 0)
|
||||||
|
.select(
|
||||||
|
F.regexp_extract(record, "White \"([^\"]*)\"", 1).as("white_id"),
|
||||||
|
F.regexp_extract(record, "Black \"([^\"]*)\"", 1).as("black_id"),
|
||||||
|
result.as("result"),
|
||||||
|
plies.as("move_count"),
|
||||||
|
F.concat(F.lit("[Event "), record).as("pgn"),
|
||||||
|
)
|
||||||
|
.filter((F.col("white_id") =!= "").and(F.col("black_id") =!= ""))
|
||||||
|
|
||||||
|
/** Turns an http(s)/ftp URL into a cluster-local path by fetching it once with SparkContext.addFile, which
|
||||||
|
* distributes the file to every executor. `.zst` is decompressed in-process and the plain `.pgn` is redistributed.
|
||||||
|
* Non-URL paths are returned unchanged.
|
||||||
|
*/
|
||||||
|
private def resolvePath(spark: SparkSession, path: String): String =
|
||||||
|
if !path.matches("^(https?|ftp)://.*") then path
|
||||||
|
else
|
||||||
|
spark.sparkContext.addFile(path)
|
||||||
|
val local = SparkFiles.get(baseName(path))
|
||||||
|
if !local.endsWith(".zst") then "file://" + local
|
||||||
|
else distribute(spark, decompressZstd(local))
|
||||||
|
|
||||||
|
private def baseName(path: String): String = path.substring(path.lastIndexOf('/') + 1)
|
||||||
|
|
||||||
|
private def distribute(spark: SparkSession, localPath: String): String =
|
||||||
|
spark.sparkContext.addFile("file://" + localPath)
|
||||||
|
"file://" + SparkFiles.get(baseName(localPath))
|
||||||
|
|
||||||
|
/** Decompresses a `.zst` file to a temp `.pgn` using zstd-jni (bundled with Spark at runtime). */
|
||||||
|
private def decompressZstd(srcPath: String): String =
|
||||||
|
val out = java.io.File.createTempFile("lichess-", ".pgn")
|
||||||
|
out.deleteOnExit()
|
||||||
|
val in = com.github.luben.zstd.ZstdInputStream(
|
||||||
|
java.io.BufferedInputStream(java.io.FileInputStream(srcPath)),
|
||||||
|
)
|
||||||
|
try java.nio.file.Files.copy(in, out.toPath, java.nio.file.StandardCopyOption.REPLACE_EXISTING)
|
||||||
|
finally in.close()
|
||||||
|
out.getAbsolutePath
|
||||||
@@ -37,15 +37,8 @@ object OpeningBookJob:
|
|||||||
outputDir: String,
|
outputDir: String,
|
||||||
maxPlies: Int,
|
maxPlies: Int,
|
||||||
): Unit =
|
): Unit =
|
||||||
val games = spark.read
|
val games = GameSource
|
||||||
.format("jdbc")
|
.load(spark, jdbcUrl, dbUser, dbPass)
|
||||||
.option("url", jdbcUrl)
|
|
||||||
.option("dbtable", "game_records")
|
|
||||||
.option("user", dbUser)
|
|
||||||
.option("password", dbPass)
|
|
||||||
.option("driver", "org.postgresql.Driver")
|
|
||||||
.option("fetchsize", "10000")
|
|
||||||
.load()
|
|
||||||
.select("pgn", "result")
|
.select("pgn", "result")
|
||||||
.filter(F.col("result").isNotNull.and(F.col("pgn").isNotNull))
|
.filter(F.col("result").isNotNull.and(F.col("pgn").isNotNull))
|
||||||
|
|
||||||
@@ -79,15 +72,16 @@ object OpeningBookJob:
|
|||||||
.option("header", "true")
|
.option("header", "true")
|
||||||
.csv(s"$outputDir/opening_book_top1000")
|
.csv(s"$outputDir/opening_book_top1000")
|
||||||
|
|
||||||
top1000.write
|
if !GameSource.isPgnMode then
|
||||||
.mode("overwrite")
|
top1000.write
|
||||||
.format("jdbc")
|
.mode("overwrite")
|
||||||
.option("url", jdbcUrl)
|
.format("jdbc")
|
||||||
.option("dbtable", "analytics_opening_stats")
|
.option("url", jdbcUrl)
|
||||||
.option("user", dbUser)
|
.option("dbtable", "analytics_opening_stats")
|
||||||
.option("password", dbPass)
|
.option("user", dbUser)
|
||||||
.option("driver", "org.postgresql.Driver")
|
.option("password", dbPass)
|
||||||
.save()
|
.option("driver", "org.postgresql.Driver")
|
||||||
|
.save()
|
||||||
|
|
||||||
/** Extracts the first `maxPlies` moves from a PGN column as a space-separated string.
|
/** Extracts the first `maxPlies` moves from a PGN column as a space-separated string.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -50,15 +50,8 @@ object PlayerClusteringJob:
|
|||||||
outputDir: String,
|
outputDir: String,
|
||||||
k: Int,
|
k: Int,
|
||||||
): Unit =
|
): Unit =
|
||||||
val games = spark.read
|
val games = GameSource
|
||||||
.format("jdbc")
|
.load(spark, jdbcUrl, dbUser, dbPass)
|
||||||
.option("url", jdbcUrl)
|
|
||||||
.option("dbtable", "game_records")
|
|
||||||
.option("user", dbUser)
|
|
||||||
.option("password", dbPass)
|
|
||||||
.option("driver", "org.postgresql.Driver")
|
|
||||||
.option("fetchsize", "10000")
|
|
||||||
.load()
|
|
||||||
.select("white_id", "black_id", "result", "move_count")
|
.select("white_id", "black_id", "result", "move_count")
|
||||||
.filter(F.col("result").isNotNull)
|
.filter(F.col("result").isNotNull)
|
||||||
|
|
||||||
@@ -126,25 +119,26 @@ object PlayerClusteringJob:
|
|||||||
.option("header", "true")
|
.option("header", "true")
|
||||||
.csv(s"$outputDir/cluster_archetypes")
|
.csv(s"$outputDir/cluster_archetypes")
|
||||||
|
|
||||||
clustersDf.write
|
if !GameSource.isPgnMode then
|
||||||
.mode("overwrite")
|
clustersDf.write
|
||||||
.format("jdbc")
|
.mode("overwrite")
|
||||||
.option("url", jdbcUrl)
|
.format("jdbc")
|
||||||
.option("dbtable", "analytics_player_clusters")
|
.option("url", jdbcUrl)
|
||||||
.option("user", dbUser)
|
.option("dbtable", "analytics_player_clusters")
|
||||||
.option("password", dbPass)
|
.option("user", dbUser)
|
||||||
.option("driver", "org.postgresql.Driver")
|
.option("password", dbPass)
|
||||||
.save()
|
.option("driver", "org.postgresql.Driver")
|
||||||
|
.save()
|
||||||
|
|
||||||
archetypes.write
|
archetypes.write
|
||||||
.mode("overwrite")
|
.mode("overwrite")
|
||||||
.format("jdbc")
|
.format("jdbc")
|
||||||
.option("url", jdbcUrl)
|
.option("url", jdbcUrl)
|
||||||
.option("dbtable", "analytics_cluster_archetypes")
|
.option("dbtable", "analytics_cluster_archetypes")
|
||||||
.option("user", dbUser)
|
.option("user", dbUser)
|
||||||
.option("password", dbPass)
|
.option("password", dbPass)
|
||||||
.option("driver", "org.postgresql.Driver")
|
.option("driver", "org.postgresql.Driver")
|
||||||
.save()
|
.save()
|
||||||
|
|
||||||
private def buildPlayerStats(games: org.apache.spark.sql.DataFrame): org.apache.spark.sql.DataFrame =
|
private def buildPlayerStats(games: org.apache.spark.sql.DataFrame): org.apache.spark.sql.DataFrame =
|
||||||
val asWhite = games.select(
|
val asWhite = games.select(
|
||||||
|
|||||||
@@ -53,15 +53,8 @@ object PlayerGraphJob:
|
|||||||
dbPass: String,
|
dbPass: String,
|
||||||
outputDir: String,
|
outputDir: String,
|
||||||
): Unit =
|
): Unit =
|
||||||
val gamesRdd: RDD[Row] = spark.read
|
val gamesRdd: RDD[Row] = GameSource
|
||||||
.format("jdbc")
|
.load(spark, jdbcUrl, dbUser, dbPass)
|
||||||
.option("url", jdbcUrl)
|
|
||||||
.option("dbtable", "game_records")
|
|
||||||
.option("user", dbUser)
|
|
||||||
.option("password", dbPass)
|
|
||||||
.option("driver", "org.postgresql.Driver")
|
|
||||||
.option("fetchsize", "10000")
|
|
||||||
.load()
|
|
||||||
.select("white_id", "black_id", "result")
|
.select("white_id", "black_id", "result")
|
||||||
.filter(F.col("result").isNotNull)
|
.filter(F.col("result").isNotNull)
|
||||||
.rdd
|
.rdd
|
||||||
@@ -116,15 +109,16 @@ object PlayerGraphJob:
|
|||||||
.mode("overwrite")
|
.mode("overwrite")
|
||||||
.parquet(s"$outputDir/player_graph")
|
.parquet(s"$outputDir/player_graph")
|
||||||
|
|
||||||
result.write
|
if !GameSource.isPgnMode then
|
||||||
.mode("overwrite")
|
result.write
|
||||||
.format("jdbc")
|
.mode("overwrite")
|
||||||
.option("url", jdbcUrl)
|
.format("jdbc")
|
||||||
.option("dbtable", "analytics_player_graph")
|
.option("url", jdbcUrl)
|
||||||
.option("user", dbUser)
|
.option("dbtable", "analytics_player_graph")
|
||||||
.option("password", dbPass)
|
.option("user", dbUser)
|
||||||
.option("driver", "org.postgresql.Driver")
|
.option("password", dbPass)
|
||||||
.save()
|
.option("driver", "org.postgresql.Driver")
|
||||||
|
.save()
|
||||||
|
|
||||||
// How many players belong to each connected component?
|
// How many players belong to each connected component?
|
||||||
// A large dominant component + many singletons is the expected shape.
|
// A large dominant component + many singletons is the expected shape.
|
||||||
|
|||||||
@@ -34,15 +34,8 @@ object PlayerStatsJob:
|
|||||||
dbPass: String,
|
dbPass: String,
|
||||||
outputDir: String,
|
outputDir: String,
|
||||||
): Unit =
|
): Unit =
|
||||||
val games = spark.read
|
val games = GameSource
|
||||||
.format("jdbc")
|
.load(spark, jdbcUrl, dbUser, dbPass)
|
||||||
.option("url", jdbcUrl)
|
|
||||||
.option("dbtable", "game_records")
|
|
||||||
.option("user", dbUser)
|
|
||||||
.option("password", dbPass)
|
|
||||||
.option("driver", "org.postgresql.Driver")
|
|
||||||
.option("fetchsize", "10000")
|
|
||||||
.load()
|
|
||||||
.select("white_id", "black_id", "result", "move_count")
|
.select("white_id", "black_id", "result", "move_count")
|
||||||
.filter(F.col("result").isNotNull)
|
.filter(F.col("result").isNotNull)
|
||||||
|
|
||||||
@@ -84,12 +77,13 @@ object PlayerStatsJob:
|
|||||||
.mode("overwrite")
|
.mode("overwrite")
|
||||||
.parquet(s"$outputDir/player_stats")
|
.parquet(s"$outputDir/player_stats")
|
||||||
|
|
||||||
stats.write
|
if !GameSource.isPgnMode then
|
||||||
.mode("overwrite")
|
stats.write
|
||||||
.format("jdbc")
|
.mode("overwrite")
|
||||||
.option("url", jdbcUrl)
|
.format("jdbc")
|
||||||
.option("dbtable", "analytics_player_stats")
|
.option("url", jdbcUrl)
|
||||||
.option("user", dbUser)
|
.option("dbtable", "analytics_player_stats")
|
||||||
.option("password", dbPass)
|
.option("user", dbUser)
|
||||||
.option("driver", "org.postgresql.Driver")
|
.option("password", dbPass)
|
||||||
.save()
|
.option("driver", "org.postgresql.Driver")
|
||||||
|
.save()
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=2
|
MINOR=4
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -205,3 +205,25 @@
|
|||||||
|
|
||||||
* **dependencies:** correct Jackson databind dependency group ID ([008d72d](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/008d72d826707c04205bac7de25170fae5fed861))
|
* **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))
|
* IO microservice ([#38](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/38)) ([a386f57](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a386f57c21d34ead6cc6f92836c52b714597e289))
|
||||||
|
## (2026-06-21)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **api:** define shared EventEnvelope and EventType for Redis EventBus ([#61](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/61)) ([595c172](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/595c172900da99de367c274488c3ccbeaef55882))
|
||||||
|
* **core:** publish GameOver event to Redis Streams ([#64](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/64)) ([676e411](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/676e4110c0893917d8bc7f836db6a19c69c5e9a5))
|
||||||
|
* **dto:** update GameWritebackEventDto for JSON deserialization and remove unused mixin ([576e3fe](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/576e3fea9bf1082549ea53efd3288474c42be93d))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* **game:** add GET /{gameId}/fen-history endpoint ([fba324a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fba324a5b01c23f97e28621ad8b72265701e0f11))
|
||||||
|
* 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))
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package de.nowchess.api.dto
|
||||||
|
|
||||||
|
final case class FenHistoryDto(fens: List[String])
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=17
|
MINOR=18
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -2109,3 +2109,149 @@
|
|||||||
|
|
||||||
* 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-06-21)
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
* **core:** publish GameOver event to Redis Streams ([#64](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/64)) ([676e411](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/676e4110c0893917d8bc7f836db6a19c69c5e9a5))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* **game:** add GET /{gameId}/fen-history endpoint ([fba324a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fba324a5b01c23f97e28621ad8b72265701e0f11))
|
||||||
|
* 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-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* 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))
|
||||||
|
* **redis:** implement game writeback stream processing with error handling and retries ([ae3ef76](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ae3ef766e8b7596a09e466cd4fb386119f17ca5c))
|
||||||
|
* **reflection:** add native reflection configuration for tournament classes ([e318250](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e31825021c0fca7cbe7d9f85755646114c83cf0c))
|
||||||
|
* **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))
|
||||||
|
* **pgn:** add SAN disambiguation and check/checkmate suffixes [NCS-42] ([#56](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/56)) ([2579539](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2579539084152178f4482ddb7b84b7f1162f10da))
|
||||||
|
* **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-06-21)
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
* **core:** publish GameOver event to Redis Streams ([#64](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/64)) ([676e411](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/676e4110c0893917d8bc7f836db6a19c69c5e9a5))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* **game:** add GET /{gameId}/fen-history endpoint ([fba324a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/fba324a5b01c23f97e28621ad8b72265701e0f11))
|
||||||
|
* 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-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* 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))
|
||||||
|
* **redis:** implement game writeback stream processing with error handling and retries ([ae3ef76](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/ae3ef766e8b7596a09e466cd4fb386119f17ca5c))
|
||||||
|
* **reflection:** add native reflection configuration for tournament classes ([e318250](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/e31825021c0fca7cbe7d9f85755646114c83cf0c))
|
||||||
|
* **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))
|
||||||
|
* **pgn:** add SAN disambiguation and check/checkmate suffixes [NCS-42] ([#56](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/56)) ([2579539](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/2579539084152178f4482ddb7b84b7f1162f10da))
|
||||||
|
* **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))
|
||||||
|
|||||||
@@ -339,6 +339,18 @@ class GameResource:
|
|||||||
log.infof("Imported PGN game %s", entry.gameId)
|
log.infof("Imported PGN game %s", entry.gameId)
|
||||||
created(GameDtoMapper.toGameFullDto(entry, ioClient))
|
created(GameDtoMapper.toGameFullDto(entry, ioClient))
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{gameId}/fen-history")
|
||||||
|
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||||
|
def getFenHistory(@PathParam("gameId") gameId: String): Response =
|
||||||
|
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||||
|
val engine = entry.engine
|
||||||
|
val initial = engine.initialContext
|
||||||
|
val moves = engine.context.moves
|
||||||
|
val contexts = moves.scanLeft(initial)((ctx, move) => engine.ruleSet.applyMove(ctx)(move))
|
||||||
|
val fens = contexts.map(ctx => ioClient.exportFen(ctx))
|
||||||
|
ok(FenHistoryDto(fens))
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{gameId}/export/fen")
|
@Path("/{gameId}/export/fen")
|
||||||
@Produces(Array(MediaType.TEXT_PLAIN))
|
@Produces(Array(MediaType.TEXT_PLAIN))
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=51
|
MINOR=53
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -281,3 +281,92 @@
|
|||||||
### 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-06-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))
|
||||||
|
* **analytics:** add Spark batch analytics module ([#70](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/70)) ([39f1657](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39f1657e1db6e84889af338c43be8cb5c03c3ec3))
|
||||||
|
* **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))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* 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))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **official-bots:** consume GameOver stream for bot cleanup ([#67](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/67)) ([db9d153](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/db9d1533912f4b41c4d1ca80ccffdde5d23d6ff6))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable official bots to connect to external tournament server ([#71](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/71)) ([688d30e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/688d30e2b10026923372be5fca3c63eaaee2de2a))
|
||||||
|
* **official-bots:** configure JWT verification ([#72](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/72)) ([98c64fc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/98c64fc0d56dc542beb31c75f4b9056d91de03cd))
|
||||||
|
* **official-bots:** NCS-70-auto-register official bots with account service ([#59](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/59)) ([7117a93](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7117a93376272094d0b1a6abf2121254ce396684))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-06-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))
|
||||||
|
* **analytics:** add Spark batch analytics module ([#70](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/70)) ([39f1657](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39f1657e1db6e84889af338c43be8cb5c03c3ec3))
|
||||||
|
* **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))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* 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))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **official-bots:** consume GameOver stream for bot cleanup ([#67](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/67)) ([db9d153](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/db9d1533912f4b41c4d1ca80ccffdde5d23d6ff6))
|
||||||
|
* **official-bots:** park expert bot on tournament server at startup ([#75](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/75)) ([30295a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/30295a4bb95855ee8261c92278bb9ebc80ee12ee))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable official bots to connect to external tournament server ([#71](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/71)) ([688d30e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/688d30e2b10026923372be5fca3c63eaaee2de2a))
|
||||||
|
* **official-bots:** configure JWT verification ([#72](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/72)) ([98c64fc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/98c64fc0d56dc542beb31c75f4b9056d91de03cd))
|
||||||
|
* **official-bots:** NCS-70-auto-register official bots with account service ([#59](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/59)) ([7117a93](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7117a93376272094d0b1a6abf2121254ce396684))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
## (2026-06-21)
|
||||||
|
|
||||||
|
### 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))
|
||||||
|
* **analytics:** add Spark batch analytics module ([#70](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/70)) ([39f1657](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39f1657e1db6e84889af338c43be8cb5c03c3ec3))
|
||||||
|
* **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))
|
||||||
|
* **events:** migrate game-creation and bot flows to Redis Streams NCS-89 ([#62](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/62)) ([a24924c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a24924c23057db3d700a75dbc4333557789cd991))
|
||||||
|
* 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))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **official-bots:** consume GameOver stream for bot cleanup ([#67](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/67)) ([db9d153](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/db9d1533912f4b41c4d1ca80ccffdde5d23d6ff6))
|
||||||
|
* **official-bots:** park expert bot on tournament server at startup ([#75](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/75)) ([30295a4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/30295a4bb95855ee8261c92278bb9ebc80ee12ee))
|
||||||
|
* true-microservices ([#40](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/40)) ([5909242](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/590924254e8a2754de661a57a03e43f89ceb6299))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable official bots to connect to external tournament server ([#71](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/71)) ([688d30e](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/688d30e2b10026923372be5fca3c63eaaee2de2a))
|
||||||
|
* **official-bots:** configure JWT verification ([#72](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/72)) ([98c64fc](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/98c64fc0d56dc542beb31c75f4b9056d91de03cd))
|
||||||
|
* **official-bots:** NCS-70-auto-register official bots with account service ([#59](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/59)) ([7117a93](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/7117a93376272094d0b1a6abf2121254ce396684))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "refactor: update metrics paths formatting in application.yml for clarity" ([3870566](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/38705663498d5f47c40dafe2f26198589ede8656))
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ quarkus:
|
|||||||
enabled: true
|
enabled: true
|
||||||
log:
|
log:
|
||||||
level: INFO
|
level: INFO
|
||||||
|
mp:
|
||||||
|
jwt:
|
||||||
|
verify:
|
||||||
|
publickey:
|
||||||
|
location: ${JWT_PUBLIC_KEY_PATH:keys/public.pem}
|
||||||
|
issuer: nowchess
|
||||||
|
|
||||||
nowchess:
|
nowchess:
|
||||||
redis:
|
redis:
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxDsnsCAl0vQx7Vu9CLDZ
|
||||||
|
g0SG05NgUzu9T+3DTEaHGq60T2uriO8BenwyvsF3BnDqTbKf4voohZ1DNfzdbT1J
|
||||||
|
Fj8B62FrDmxcO+sp1/b5HUCJP6y2uSRCmzOHe5k7Pk1IEi72FgBpKXSRkFibRlVf
|
||||||
|
634g7mgsPZAQ9PJEsv4Qvm05T9L6+Gmq6N3bMVLKRXs4RhDhaFbYH9GtUg1eI0yH
|
||||||
|
YjGyRfqzW/nqVMstOLHt8CuPouq4p7eMzeDH3YHkxPm4GG5foCXMOd2DZrW0SCcr
|
||||||
|
7dhFeNVWzQ2m53eOhBzNQX+v3pgjVStsePhBRt2LyGfwkNzmqDgqWsMzSHRMY+cn
|
||||||
|
WQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
+1
@@ -2,6 +2,7 @@ package de.nowchess.bot.resource
|
|||||||
|
|
||||||
case class JoinTournamentRequest(
|
case class JoinTournamentRequest(
|
||||||
tournamentId: String,
|
tournamentId: String,
|
||||||
|
botToken: String,
|
||||||
difficulty: String,
|
difficulty: String,
|
||||||
serverUrl: Option[String],
|
serverUrl: Option[String],
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ class TournamentJoinResource:
|
|||||||
difficulty,
|
difficulty,
|
||||||
serverUrl,
|
serverUrl,
|
||||||
)
|
)
|
||||||
player.joinTournament(req.tournamentId, difficulty, serverUrl) match
|
player.joinTournament(req.tournamentId, req.botToken, difficulty, serverUrl) match
|
||||||
case Right(botId) =>
|
case Right(botId) =>
|
||||||
val resp = JoinTournamentResponse(botId, difficulty, "joining")
|
val resp = JoinTournamentResponse(botId, difficulty, "joining")
|
||||||
Response.ok(resp).build()
|
Response.ok(resp).build()
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ object TournamentBotConfig:
|
|||||||
tournamentId <- env.get("TOURNAMENT_ID").filter(_.nonEmpty)
|
tournamentId <- env.get("TOURNAMENT_ID").filter(_.nonEmpty)
|
||||||
token <- env.get("TOURNAMENT_BOT_TOKEN").filter(_.nonEmpty)
|
token <- env.get("TOURNAMENT_BOT_TOKEN").filter(_.nonEmpty)
|
||||||
botId <- jwtSubject(token)
|
botId <- jwtSubject(token)
|
||||||
serverUrl = env.getOrElse("TOURNAMENT_SERVER_URL", "http://localhost:8089")
|
serverUrl = env.getOrElse("TOURNAMENT_SERVER_URL", "http://141.37.123.132:8086")
|
||||||
difficulty = env.getOrElse("TOURNAMENT_BOT_DIFFICULTY", "medium")
|
difficulty = env.getOrElse("TOURNAMENT_BOT_DIFFICULTY", "medium")
|
||||||
yield TournamentBotConfig(serverUrl, tournamentId, token, botId, difficulty)
|
yield TournamentBotConfig(serverUrl, tournamentId, token, botId, difficulty)
|
||||||
|
|
||||||
|
|||||||
+41
-26
@@ -39,10 +39,11 @@ class TournamentBotGamePlayer:
|
|||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
val defaultServerUrl: String =
|
val defaultServerUrl: String =
|
||||||
System.getenv().asScala.getOrElse("TOURNAMENT_SERVER_URL", "http://localhost:8089")
|
System.getenv().asScala.getOrElse("TOURNAMENT_SERVER_URL", "http://141.37.123.132:8086")
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
def initialize(): Unit =
|
def initialize(): Unit =
|
||||||
|
parkOnStartup()
|
||||||
config match
|
config match
|
||||||
case None =>
|
case None =>
|
||||||
log.info("Tournament bot disabled — set TOURNAMENT_ID and TOURNAMENT_BOT_TOKEN to enable")
|
log.info("Tournament bot disabled — set TOURNAMENT_ID and TOURNAMENT_BOT_TOKEN to enable")
|
||||||
@@ -50,11 +51,45 @@ class TournamentBotGamePlayer:
|
|||||||
log.infof("Tournament bot enabled — server=%s tournament=%s bot=%s", cfg.serverUrl, cfg.tournamentId, cfg.botId)
|
log.infof("Tournament bot enabled — server=%s tournament=%s bot=%s", cfg.serverUrl, cfg.tournamentId, cfg.botId)
|
||||||
startAsync(cfg)
|
startAsync(cfg)
|
||||||
|
|
||||||
def joinTournament(tournamentId: String, difficulty: String, serverUrl: String): Either[String, String] =
|
private def parkOnStartup(): Unit =
|
||||||
registerBot(serverUrl, difficulty) match
|
park(defaultServerUrl, "expert") match
|
||||||
case None => Left("Failed to register bot with tournament server")
|
case Some(id) => log.infof("Parked expert bot on %s as id %s", defaultServerUrl, id)
|
||||||
case Some((botId, token)) =>
|
case None => log.warnf("Failed to park expert bot on %s", defaultServerUrl)
|
||||||
val cfg = TournamentBotConfig(serverUrl, tournamentId, token, botId, difficulty)
|
|
||||||
|
private def park(serverUrl: String, difficulty: String): Option[String] =
|
||||||
|
System.getenv().asScala.get("TOURNAMENT_BOT_TOKEN").filter(_.nonEmpty).flatMap { token =>
|
||||||
|
Try {
|
||||||
|
val body = s"""{"name":"${botName(difficulty)}"}"""
|
||||||
|
val response = client
|
||||||
|
.target(serverUrl)
|
||||||
|
.path("api")
|
||||||
|
.path("bots")
|
||||||
|
.request(MediaType.APPLICATION_JSON)
|
||||||
|
.header("Authorization", s"Bearer $token")
|
||||||
|
.post(Entity.entity(body, MediaType.APPLICATION_JSON))
|
||||||
|
if response.getStatus == 201 || response.getStatus == 200 then
|
||||||
|
val id = objectMapper.readTree(response.readEntity(classOf[String])).path("id").asText()
|
||||||
|
response.close()
|
||||||
|
Option(id).filter(_.nonEmpty)
|
||||||
|
else {
|
||||||
|
log.warnf("Parking bot %s returned status %d", botName(difficulty), response.getStatus); response.close();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}.getOrElse(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def botName(difficulty: String): String = s"NowChess ${difficulty.capitalize}"
|
||||||
|
|
||||||
|
def joinTournament(
|
||||||
|
tournamentId: String,
|
||||||
|
botToken: String,
|
||||||
|
difficulty: String,
|
||||||
|
serverUrl: String,
|
||||||
|
): Either[String, String] =
|
||||||
|
TournamentBotConfig.jwtSubject(botToken) match
|
||||||
|
case None => Left("Invalid bot token — could not extract subject")
|
||||||
|
case Some(botId) =>
|
||||||
|
val cfg = TournamentBotConfig(serverUrl, tournamentId, botToken, botId, difficulty)
|
||||||
if join(cfg) then
|
if join(cfg) then
|
||||||
startAsync(cfg)
|
startAsync(cfg)
|
||||||
Right(botId)
|
Right(botId)
|
||||||
@@ -65,26 +100,6 @@ class TournamentBotGamePlayer:
|
|||||||
thread.setDaemon(true)
|
thread.setDaemon(true)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
private def registerBot(serverUrl: String, difficulty: String): Option[(String, String)] =
|
|
||||||
Try {
|
|
||||||
val name = s"NowChess ${difficulty.capitalize}"
|
|
||||||
val body = s"""{"name":"$name","isBot":true}"""
|
|
||||||
val response = client
|
|
||||||
.target(serverUrl)
|
|
||||||
.path("api")
|
|
||||||
.path("auth")
|
|
||||||
.path("register")
|
|
||||||
.request(MediaType.APPLICATION_JSON)
|
|
||||||
.post(Entity.entity(body, MediaType.APPLICATION_JSON))
|
|
||||||
if response.getStatus == 201 then
|
|
||||||
val node = objectMapper.readTree(response.readEntity(classOf[String]))
|
|
||||||
val id = node.path("id").asText()
|
|
||||||
val token = node.path("token").asText()
|
|
||||||
response.close()
|
|
||||||
if id.nonEmpty && token.nonEmpty then Some((id, token)) else None
|
|
||||||
else { log.warnf("Bot registration returned status %d", response.getStatus); response.close(); None }
|
|
||||||
}.getOrElse(None)
|
|
||||||
|
|
||||||
@PreDestroy
|
@PreDestroy
|
||||||
def cleanup(): Unit =
|
def cleanup(): Unit =
|
||||||
running = false
|
running = false
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=18
|
MINOR=21
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -23,3 +23,17 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **tournament:** replace scala.util.Random singleton with UUID for native image ([a50884a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a50884a11b1de500e74c18fd08d2d102d53cc3e9))
|
* **tournament:** replace scala.util.Random singleton with UUID for native image ([a50884a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a50884a11b1de500e74c18fd08d2d102d53cc3e9))
|
||||||
|
## (2026-06-21)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **analytics:** add Spark batch analytics module ([#70](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/70)) ([39f1657](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/39f1657e1db6e84889af338c43be8cb5c03c3ec3))
|
||||||
|
* NCS-121 pipeline for tournament ([#68](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/68)) ([145f467](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/145f4676483f92bfe6f2d9ca40e2cb4200982e87))
|
||||||
|
* NCS-82 add Swiss-system tournament module ([#55](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/55)) ([c5661de](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/c5661de4a0ebf4b33211f5a391840dcf744656b7))
|
||||||
|
* **reflection:** add GameWritebackEventDto to native reflection configuration ([1aee39c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/1aee39c1ad286984501ac4b47da2b72d60b58a6f))
|
||||||
|
* **reflection:** add native reflection configuration for tournament classes ([65bc6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/65bc6a759937543df2d29905688bfa9e68d0c9d4))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **tournament:** replace scala.util.Random singleton with UUID for native image ([a50884a](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/a50884a11b1de500e74c18fd08d2d102d53cc3e9))
|
||||||
|
* wrap server list response in ExternalTournamentServerList ([f2d79e4](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/f2d79e4952aea6bde762c294eb202474b7827054))
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
package de.nowchess.tournament.resource
|
package de.nowchess.tournament.resource
|
||||||
|
|
||||||
import de.nowchess.tournament.dto.{ErrorDto, RegisterServerRequest}
|
import de.nowchess.tournament.dto.{ErrorDto, ExternalTournamentServerList, RegisterServerRequest}
|
||||||
import de.nowchess.tournament.service.TournamentServerRegistry
|
import de.nowchess.tournament.service.TournamentServerRegistry
|
||||||
import jakarta.annotation.security.RolesAllowed
|
import jakarta.annotation.security.RolesAllowed
|
||||||
import jakarta.enterprise.context.ApplicationScoped
|
import jakarta.enterprise.context.ApplicationScoped
|
||||||
@@ -22,7 +22,7 @@ class TournamentServerResource:
|
|||||||
|
|
||||||
@GET
|
@GET
|
||||||
def list(): Response =
|
def list(): Response =
|
||||||
Response.ok(registry.list()).build()
|
Response.ok(ExternalTournamentServerList(registry.list())).build()
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
def register(req: RegisterServerRequest): Response =
|
def register(req: RegisterServerRequest): Response =
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=3
|
MINOR=4
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
@@ -259,3 +259,32 @@
|
|||||||
### 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-06-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))
|
||||||
|
* 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))
|
||||||
|
* **reflection:** add native reflection configuration for tournament classes ([65bc6a7](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/65bc6a759937543df2d29905688bfa9e68d0c9d4))
|
||||||
|
* 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))
|
||||||
|
* **ws:** migrate challenge notifications to Redis Streams ([#66](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/66)) ([55f102c](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/55f102cbaa684be94a158b16aaa42a50b36afaf3))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* NCS-122 authenticate WebSocket connections via first-message auth ([#73](https://git.janis-eccarius.de/NowChess/NowChessSystems/issues/73)) ([343e2bd](https://git.janis-eccarius.de/NowChess/NowChessSystems/commit/343e2bdd100649a96d96da8a6d98caad6de4ad14))
|
||||||
|
* 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))
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package de.nowchess.ws.resource
|
|||||||
import de.nowchess.ws.config.RedisConfig
|
import de.nowchess.ws.config.RedisConfig
|
||||||
import io.micrometer.core.instrument.{Counter, Gauge, MeterRegistry}
|
import io.micrometer.core.instrument.{Counter, Gauge, MeterRegistry}
|
||||||
import io.quarkus.redis.datasource.RedisDataSource
|
import io.quarkus.redis.datasource.RedisDataSource
|
||||||
import io.quarkus.redis.datasource.pubsub.PubSubCommands
|
|
||||||
import io.quarkus.websockets.next.*
|
import io.quarkus.websockets.next.*
|
||||||
import io.smallrye.jwt.auth.principal.JWTParser
|
import io.smallrye.jwt.auth.principal.JWTParser
|
||||||
import jakarta.annotation.PostConstruct
|
import jakarta.annotation.PostConstruct
|
||||||
@@ -34,6 +33,7 @@ class GameWebSocketResource:
|
|||||||
// scalafix:on DisableSyntax.var
|
// scalafix:on DisableSyntax.var
|
||||||
|
|
||||||
private val connections = new ConcurrentHashMap[String, ConnectionMeta]()
|
private val connections = new ConcurrentHashMap[String, ConnectionMeta]()
|
||||||
|
private val pendingAuth = ConcurrentHashMap.newKeySet[String]()
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
def initializeMetrics(): Unit = {
|
def initializeMetrics(): Unit = {
|
||||||
@@ -64,40 +64,60 @@ class GameWebSocketResource:
|
|||||||
s"${redisConfig.prefix}:game:$gameId:c2s"
|
s"${redisConfig.prefix}:game:$gameId:c2s"
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
def onOpen(connection: WebSocketConnection, handshake: HandshakeRequest): Unit =
|
def onOpen(connection: WebSocketConnection): Unit =
|
||||||
activeGauge
|
activeGauge
|
||||||
val gameId = connection.pathParam("gameId")
|
val gameId = connection.pathParam("gameId")
|
||||||
val playerId = resolvePlayerId(handshake)
|
|
||||||
log.infof("Game WebSocket opened — gameId=%s playerId=%s", gameId, playerId.getOrElse("anonymous"))
|
|
||||||
val handler: Consumer[String] = msg => connection.sendText(msg).subscribe().`with`(_ => (), _ => ())
|
val handler: Consumer[String] = msg => connection.sendText(msg).subscribe().`with`(_ => (), _ => ())
|
||||||
val subscriber = redis.pubsub(classOf[String]).subscribe(s2cTopic(gameId), handler)
|
val subscriber = redis.pubsub(classOf[String]).subscribe(s2cTopic(gameId), handler)
|
||||||
connections.put(connection.id(), ConnectionMeta(gameId, subscriber, playerId))
|
connections.put(connection.id(), ConnectionMeta(gameId, subscriber, None))
|
||||||
connectionsOpened.increment()
|
connectionsOpened.increment()
|
||||||
publishConnected(gameId, playerId)
|
pendingAuth.add(connection.id())
|
||||||
|
log.infof("Game WebSocket opened — gameId=%s connId=%s awaiting auth", gameId, connection.id())
|
||||||
|
|
||||||
@OnTextMessage
|
@OnTextMessage
|
||||||
def onTextMessage(connection: WebSocketConnection, message: String): Unit =
|
def onTextMessage(connection: WebSocketConnection, message: String): Unit =
|
||||||
messagesReceived.increment()
|
messagesReceived.increment()
|
||||||
Option(connections.get(connection.id())).foreach { meta =>
|
if pendingAuth.remove(connection.id()) then
|
||||||
val enriched = meta.playerId match
|
val playerIdOpt =
|
||||||
case Some(pid) => injectPlayerId(message, pid)
|
parseAuthToken(message)
|
||||||
case None => message
|
.flatMap(token => Try(jwtParser.parse(token)).toOption)
|
||||||
redis.pubsub(classOf[String]).publish(c2sTopic(meta.gameId), enriched)
|
.map(_.getSubject)
|
||||||
}
|
playerIdOpt match
|
||||||
|
case None =>
|
||||||
|
log.warnf("Game WebSocket auth failed — closing connId=%s", connection.id())
|
||||||
|
connection.close().subscribe().`with`(_ => (), _ => ())
|
||||||
|
case Some(playerId) =>
|
||||||
|
Option(connections.get(connection.id())).foreach { meta =>
|
||||||
|
connections.put(connection.id(), meta.copy(playerId = Some(playerId)))
|
||||||
|
publishConnected(meta.gameId, Some(playerId))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Option(connections.get(connection.id())).foreach { meta =>
|
||||||
|
val enriched = meta.playerId match
|
||||||
|
case Some(pid) => injectPlayerId(message, pid)
|
||||||
|
case None => message
|
||||||
|
redis.pubsub(classOf[String]).publish(c2sTopic(meta.gameId), enriched)
|
||||||
|
}
|
||||||
|
|
||||||
@OnClose
|
@OnClose
|
||||||
def onClose(connection: WebSocketConnection): Unit =
|
def onClose(connection: WebSocketConnection): Unit =
|
||||||
|
pendingAuth.remove(connection.id())
|
||||||
Option(connections.remove(connection.id())).foreach { meta =>
|
Option(connections.remove(connection.id())).foreach { meta =>
|
||||||
log.infof("Game WebSocket closed — gameId=%s", meta.gameId)
|
log.infof("Game WebSocket closed — gameId=%s", meta.gameId)
|
||||||
meta.subscriber.unsubscribe(s2cTopic(meta.gameId))
|
meta.subscriber.unsubscribe(s2cTopic(meta.gameId))
|
||||||
connectionsClosed.increment()
|
connectionsClosed.increment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private def resolvePlayerId(handshake: HandshakeRequest): Option[String] =
|
private def parseAuthToken(message: String): Option[String] =
|
||||||
Option(handshake.header("Authorization"))
|
val trimmed = message.trim
|
||||||
.filter(_.nonEmpty)
|
if !trimmed.contains("\"type\":\"auth\"") then None
|
||||||
.flatMap(token => Try(jwtParser.parse(token)).toOption)
|
else
|
||||||
.map(_.getSubject)
|
val start = trimmed.indexOf("\"token\":\"")
|
||||||
|
if start < 0 then None
|
||||||
|
else
|
||||||
|
val valueStart = start + 9
|
||||||
|
val end = trimmed.indexOf('"', valueStart)
|
||||||
|
if end < 0 then None else Some(trimmed.substring(valueStart, end)).filter(_.nonEmpty)
|
||||||
|
|
||||||
private def publishConnected(gameId: String, playerId: Option[String]): Unit =
|
private def publishConnected(gameId: String, playerId: Option[String]): Unit =
|
||||||
val connectedMsg = playerId match
|
val connectedMsg = playerId match
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class UserWebSocketResource:
|
|||||||
private val maxStreamLen = 1000L
|
private val maxStreamLen = 1000L
|
||||||
|
|
||||||
private val connections = new ConcurrentHashMap[String, (String, WebSocketConnection)]()
|
private val connections = new ConcurrentHashMap[String, (String, WebSocketConnection)]()
|
||||||
|
private val pendingAuth = ConcurrentHashMap.newKeySet[String]()
|
||||||
|
|
||||||
private def userStreamKey(userId: String): String =
|
private def userStreamKey(userId: String): String =
|
||||||
s"${redisConfig.prefix}:user:$userId:events:stream"
|
s"${redisConfig.prefix}:user:$userId:events:stream"
|
||||||
@@ -39,29 +40,34 @@ class UserWebSocketResource:
|
|||||||
private def dlqKey: String = s"${redisConfig.prefix}:dlq"
|
private def dlqKey: String = s"${redisConfig.prefix}:dlq"
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
def onOpen(connection: WebSocketConnection, handshake: HandshakeRequest): Unit =
|
def onOpen(connection: WebSocketConnection): Unit =
|
||||||
val userIdOpt = Option(handshake.header("Authorization"))
|
pendingAuth.add(connection.id())
|
||||||
.filter(_.nonEmpty)
|
|
||||||
.flatMap(token => Try(jwtParser.parse(token)).toOption)
|
|
||||||
.map(_.getSubject)
|
|
||||||
|
|
||||||
userIdOpt match
|
@OnTextMessage
|
||||||
case None =>
|
def onTextMessage(connection: WebSocketConnection, message: String): Unit =
|
||||||
log.warn("WebSocket opened with no valid JWT — closing connection")
|
if pendingAuth.remove(connection.id()) then
|
||||||
connection.close().subscribe().`with`(_ => (), _ => ())
|
val userIdOpt =
|
||||||
case Some(userId) =>
|
parseAuthToken(message)
|
||||||
log.infof("User WebSocket opened — userId=%s connId=%s", userId, connection.id())
|
.flatMap(token => Try(jwtParser.parse(token)).toOption)
|
||||||
createGroupIfAbsent(userId, connection.id())
|
.map(_.getSubject)
|
||||||
connections.put(connection.id(), (userId, connection))
|
userIdOpt match
|
||||||
executor.submit(
|
case None =>
|
||||||
new Runnable:
|
log.warn("WebSocket opened with no valid JWT — closing connection")
|
||||||
def run(): Unit = pollLoop(connection.id(), userId, connection),
|
connection.close().subscribe().`with`(_ => (), _ => ())
|
||||||
)
|
case Some(userId) =>
|
||||||
val connectedMsg = s"""{"type":"CONNECTED","userId":"$userId"}"""
|
log.infof("User WebSocket opened — userId=%s connId=%s", userId, connection.id())
|
||||||
connection.sendText(connectedMsg).subscribe().`with`(_ => (), _ => ())
|
createGroupIfAbsent(userId, connection.id())
|
||||||
|
connections.put(connection.id(), (userId, connection))
|
||||||
|
executor.submit(
|
||||||
|
new Runnable:
|
||||||
|
def run(): Unit = pollLoop(connection.id(), userId, connection),
|
||||||
|
)
|
||||||
|
val connectedMsg = s"""{"type":"CONNECTED","userId":"$userId"}"""
|
||||||
|
connection.sendText(connectedMsg).subscribe().`with`(_ => (), _ => ())
|
||||||
|
|
||||||
@OnClose
|
@OnClose
|
||||||
def onClose(connection: WebSocketConnection): Unit =
|
def onClose(connection: WebSocketConnection): Unit =
|
||||||
|
pendingAuth.remove(connection.id())
|
||||||
log.infof("User WebSocket closed — connectionId=%s", connection.id())
|
log.infof("User WebSocket closed — connectionId=%s", connection.id())
|
||||||
val userIdOpt = Option(connections.remove(connection.id())).map(_._1)
|
val userIdOpt = Option(connections.remove(connection.id())).map(_._1)
|
||||||
userIdOpt.foreach { userId =>
|
userIdOpt.foreach { userId =>
|
||||||
@@ -128,3 +134,14 @@ class UserWebSocketResource:
|
|||||||
) match
|
) match
|
||||||
case Failure(ex) => log.warnf(ex, "Failed to publish to stream %s", key)
|
case Failure(ex) => log.warnf(ex, "Failed to publish to stream %s", key)
|
||||||
case Success(_) => ()
|
case Success(_) => ()
|
||||||
|
|
||||||
|
private def parseAuthToken(message: String): Option[String] =
|
||||||
|
val trimmed = message.trim
|
||||||
|
if !trimmed.contains("\"type\":\"auth\"") then None
|
||||||
|
else
|
||||||
|
val start = trimmed.indexOf("\"token\":\"")
|
||||||
|
if start < 0 then None
|
||||||
|
else
|
||||||
|
val valueStart = start + 9
|
||||||
|
val end = trimmed.indexOf('"', valueStart)
|
||||||
|
if end < 0 then None else Some(trimmed.substring(valueStart, end)).filter(_.nonEmpty)
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
MAJOR=0
|
MAJOR=0
|
||||||
MINOR=16
|
MINOR=17
|
||||||
PATCH=0
|
PATCH=0
|
||||||
|
|||||||
Reference in New Issue
Block a user