feat: NCS-53 changed IO to MicroService for easier scaling
Build & Test (NowChessSystems) TeamCity build failed
Build & Test (NowChessSystems) TeamCity build failed
This commit is contained in:
@@ -1,3 +1,8 @@
|
||||
greeting:
|
||||
message: "hello"
|
||||
|
||||
quarkus:
|
||||
http:
|
||||
port: 8080
|
||||
application:
|
||||
name: nowchess-core
|
||||
rest-client:
|
||||
io-service:
|
||||
url: http://localhost:8081
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package de.nowchess.chess.client
|
||||
|
||||
import de.nowchess.api.game.GameContext
|
||||
import de.nowchess.io.service.dto.{ImportFenRequest, ImportPgnRequest}
|
||||
import jakarta.ws.rs.*
|
||||
import jakarta.ws.rs.core.MediaType
|
||||
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient
|
||||
|
||||
@Path("/io")
|
||||
@RegisterRestClient(configKey = "io-service")
|
||||
trait IoServiceClient:
|
||||
|
||||
@POST
|
||||
@Path("/import/fen")
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
def importFen(body: ImportFenRequest): GameContext
|
||||
|
||||
@POST
|
||||
@Path("/import/pgn")
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
def importPgn(body: ImportPgnRequest): GameContext
|
||||
|
||||
@POST
|
||||
@Path("/export/fen")
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.TEXT_PLAIN))
|
||||
def exportFen(ctx: GameContext): String
|
||||
|
||||
@POST
|
||||
@Path("/export/pgn")
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array("application/x-chess-pgn"))
|
||||
def exportPgn(ctx: GameContext): String
|
||||
@@ -2,7 +2,10 @@ package de.nowchess.chess.config
|
||||
|
||||
import com.fasterxml.jackson.core.Version
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.scala.DefaultScalaModule
|
||||
import de.nowchess.api.board.Square
|
||||
import de.nowchess.io.json.{SquareKeyDeserializer, SquareKeySerializer}
|
||||
import io.quarkus.jackson.ObjectMapperCustomizer
|
||||
import jakarta.inject.Singleton
|
||||
|
||||
@@ -15,3 +18,7 @@ class JacksonConfig extends ObjectMapperCustomizer:
|
||||
new Version(2, 21, 1, null, "com.fasterxml.jackson.module", "jackson-module-scala")
|
||||
// scalafix:on DisableSyntax.null
|
||||
})
|
||||
val squareModule = new SimpleModule()
|
||||
squareModule.addKeyDeserializer(classOf[Square], new SquareKeyDeserializer())
|
||||
squareModule.addKeySerializer(classOf[Square], new SquareKeySerializer())
|
||||
mapper.registerModule(squareModule)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package de.nowchess.chess.config
|
||||
|
||||
import de.nowchess.api.board.{CastlingRights, Color, File, Piece, PieceType, Rank, Square}
|
||||
import de.nowchess.api.dto.*
|
||||
import de.nowchess.api.game.{DrawReason, GameContext, GameResult}
|
||||
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
|
||||
import io.quarkus.runtime.annotations.RegisterForReflection
|
||||
|
||||
@RegisterForReflection(
|
||||
@@ -18,6 +21,21 @@ import io.quarkus.runtime.annotations.RegisterForReflection
|
||||
classOf[LegalMovesResponseDto],
|
||||
classOf[OkResponseDto],
|
||||
classOf[PlayerInfoDto],
|
||||
|
||||
classOf[GameContext],
|
||||
classOf[Color],
|
||||
classOf[Piece],
|
||||
classOf[PieceType],
|
||||
classOf[CastlingRights],
|
||||
classOf[Square],
|
||||
classOf[File],
|
||||
classOf[Rank],
|
||||
classOf[Move],
|
||||
classOf[MoveType],
|
||||
classOf[PromotionPiece],
|
||||
classOf[GameResult],
|
||||
classOf[DrawReason],
|
||||
|
||||
),
|
||||
)
|
||||
class NativeReflectionConfig
|
||||
|
||||
@@ -6,18 +6,21 @@ import de.nowchess.api.dto.*
|
||||
import de.nowchess.api.game.{DrawReason, GameContext, GameResult}
|
||||
import de.nowchess.api.move.{Move, MoveType, PromotionPiece}
|
||||
import de.nowchess.api.player.{PlayerId, PlayerInfo}
|
||||
import de.nowchess.chess.client.IoServiceClient
|
||||
import de.nowchess.chess.controller.Parser
|
||||
import de.nowchess.chess.engine.GameEngine
|
||||
import de.nowchess.chess.exception.{BadRequestException, GameNotFoundException}
|
||||
import de.nowchess.chess.observer.*
|
||||
import de.nowchess.chess.registry.{GameEntry, GameRegistry}
|
||||
import de.nowchess.io.fen.{FenExporter, FenParser}
|
||||
import de.nowchess.io.pgn.{PgnExporter, PgnParser}
|
||||
import de.nowchess.io.fen.FenExporter
|
||||
import de.nowchess.io.pgn.PgnExporter
|
||||
import de.nowchess.io.service.dto.{ImportFenRequest, ImportPgnRequest}
|
||||
import io.smallrye.mutiny.Multi
|
||||
import jakarta.enterprise.context.ApplicationScoped
|
||||
import jakarta.inject.Inject
|
||||
import jakarta.ws.rs.*
|
||||
import jakarta.ws.rs.core.{MediaType, Response}
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import scala.compiletime.uninitialized
|
||||
@@ -32,6 +35,10 @@ class GameResource:
|
||||
|
||||
@Inject
|
||||
var objectMapper: ObjectMapper = uninitialized
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
var ioClient: IoServiceClient = uninitialized
|
||||
// scalafix:on DisableSyntax.var
|
||||
|
||||
private val DefaultWhite = PlayerInfo(PlayerId("p1"), "Player 1")
|
||||
@@ -142,7 +149,6 @@ class GameResource:
|
||||
val black = playerInfoFrom(req.black, DefaultBlack)
|
||||
val entry = newEntry(GameContext.initial, white, black)
|
||||
registry.store(entry)
|
||||
println(s"Created game ${entry.gameId}")
|
||||
created(toGameFullDto(entry))
|
||||
|
||||
@GET
|
||||
@@ -264,9 +270,7 @@ class GameResource:
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
def importFen(body: ImportFenRequestDto): Response =
|
||||
val ctx = FenParser.parseFen(body.fen) match
|
||||
case Left(err) => throw BadRequestException("INVALID_FEN", err, Some("fen"))
|
||||
case Right(ctx) => ctx
|
||||
val ctx = ioClient.importFen(ImportFenRequest(body.fen))
|
||||
val white = playerInfoFrom(body.white, DefaultWhite)
|
||||
val black = playerInfoFrom(body.black, DefaultBlack)
|
||||
val entry = newEntry(ctx, white, black)
|
||||
@@ -278,11 +282,8 @@ class GameResource:
|
||||
@Consumes(Array(MediaType.APPLICATION_JSON))
|
||||
@Produces(Array(MediaType.APPLICATION_JSON))
|
||||
def importPgn(body: ImportPgnRequestDto): Response =
|
||||
val engine = GameEngine()
|
||||
engine.loadGame(PgnParser, body.pgn) match
|
||||
case Left(err) => throw BadRequestException("INVALID_PGN", err, Some("pgn"))
|
||||
case Right(_) => ()
|
||||
val entry = GameEntry(registry.generateId(), engine, DefaultWhite, DefaultBlack)
|
||||
val ctx = ioClient.importPgn(ImportPgnRequest(body.pgn))
|
||||
val entry = newEntry(ctx, DefaultWhite, DefaultBlack)
|
||||
registry.store(entry)
|
||||
created(toGameFullDto(entry))
|
||||
|
||||
@@ -291,21 +292,12 @@ class GameResource:
|
||||
@Produces(Array(MediaType.TEXT_PLAIN))
|
||||
def exportFen(@PathParam("gameId") gameId: String): Response =
|
||||
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||
ok(FenExporter.exportGameContext(entry.engine.context))
|
||||
ok(ioClient.exportFen(entry.engine.context))
|
||||
|
||||
@GET
|
||||
@Path("/{gameId}/export/pgn")
|
||||
@Produces(Array("application/x-chess-pgn"))
|
||||
def exportPgn(@PathParam("gameId") gameId: String): Response =
|
||||
val entry = registry.get(gameId).getOrElse(throw GameNotFoundException(gameId))
|
||||
val pgn = PgnExporter.exportGame(
|
||||
Map(
|
||||
"Event" -> "NowChess game",
|
||||
"White" -> entry.white.displayName,
|
||||
"Black" -> entry.black.displayName,
|
||||
"Result" -> "*",
|
||||
),
|
||||
entry.engine.context.moves,
|
||||
)
|
||||
ok(pgn)
|
||||
ok(ioClient.exportPgn(entry.engine.context))
|
||||
// scalafix:on DisableSyntax.throw
|
||||
|
||||
Reference in New Issue
Block a user