From 4ebf67a805bbc3f2c8827d51a0019125048e9c65 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Sun, 14 Apr 2024 19:48:33 +0200 Subject: [PATCH] use BinaryFen also in in-memory caches --- src/main/scala/evalCache/EvalCacheApi.scala | 25 +++++++------ .../evalCache/EvalCacheBsonHandlers.scala | 2 +- src/main/scala/evalCache/EvalCacheEntry.scala | 3 +- src/main/scala/evalCache/EvalCacheMulti.scala | 20 +++++------ .../scala/evalCache/EvalCacheUpgrade.scala | 35 ++++++++++--------- src/main/scala/evalCache/package.scala | 15 +------- 6 files changed, 44 insertions(+), 56 deletions(-) diff --git a/src/main/scala/evalCache/EvalCacheApi.scala b/src/main/scala/evalCache/EvalCacheApi.scala index 6d5a4030..b62c27ae 100644 --- a/src/main/scala/evalCache/EvalCacheApi.scala +++ b/src/main/scala/evalCache/EvalCacheApi.scala @@ -27,16 +27,17 @@ final class EvalCacheApi(mongo: Mongo)(using import EvalCacheBsonHandlers.given def get(sri: Sri, e: EvalGet, emit: Emit[ClientIn]): Unit = - Id.from(e.variant, e.fen).foreach: id => - getEntry(id) - .map: - _.flatMap(_.makeBestMultiPvEval(e.multiPv)) - .map(monitorRequest(e.fen, Monitor.evalCache.single)) - .foreach: - _.foreach: eval => - emit: - ClientIn.EvalHit: - EvalCacheJsonHandlers.writeEval(eval, e.fen) + ("path" -> JsString(e.path.value)) + Id.from(e.variant, e.fen) + .foreach: id => + getEntry(id) + .map: + _.flatMap(_.makeBestMultiPvEval(e.multiPv)) + .map(monitorRequest(e.fen, Monitor.evalCache.single)) + .foreach: + _.foreach: eval => + emit: + ClientIn.EvalHit: + EvalCacheJsonHandlers.writeEval(eval, e.fen) + ("path" -> JsString(e.path.value)) if e.up then upgrade.register(sri, e) def getMulti(sri: Sri, e: EvalGetMulti, emit: Emit[ClientIn]): Unit = @@ -130,4 +131,6 @@ final class EvalCacheApi(mongo: Mongo)(using private object EvalCacheValidator: def apply(in: EvalCacheEntry.Input): Either[ErrorStr, Unit] = - in.eval.pvs.traverse_(pv => chess.Replay.boardsFromUci(pv.moves.value.toList, in.fen.some, in.situation.variant)) + in.eval.pvs.traverse_(pv => + chess.Replay.boardsFromUci(pv.moves.value.toList, in.fen.some, in.situation.variant) + ) diff --git a/src/main/scala/evalCache/EvalCacheBsonHandlers.scala b/src/main/scala/evalCache/EvalCacheBsonHandlers.scala index 7ea753df..ef120e04 100644 --- a/src/main/scala/evalCache/EvalCacheBsonHandlers.scala +++ b/src/main/scala/evalCache/EvalCacheBsonHandlers.scala @@ -66,7 +66,7 @@ object EvalCacheBsonHandlers: def readTry(bson: BSONValue) = bson match case v: BSONBinary => Success(BinaryFen(v.byteArray)) - case _ => handlerBadType(bson) + case _ => handlerBadType(bson) def writeTry(v: BinaryFen) = Success(BSONBinary(v.value, Subtype.GenericBinarySubtype)) given BSONHandler[Id] = Macros.handler diff --git a/src/main/scala/evalCache/EvalCacheEntry.scala b/src/main/scala/evalCache/EvalCacheEntry.scala index bea3d7c6..6a15d824 100644 --- a/src/main/scala/evalCache/EvalCacheEntry.scala +++ b/src/main/scala/evalCache/EvalCacheEntry.scala @@ -83,7 +83,8 @@ object EvalCacheEntry: case class Input(id: Id, fen: Fen.Full, situation: Situation, eval: Eval) def makeInput(variant: Variant, fen: Fen.Full, eval: Eval) = - Fen.read(variant, fen) + Fen + .read(variant, fen) .filter(_.playable(false)) .ifTrue(eval.looksValid) .map: situation => diff --git a/src/main/scala/evalCache/EvalCacheMulti.scala b/src/main/scala/evalCache/EvalCacheMulti.scala index 54c82765..a1996273 100644 --- a/src/main/scala/evalCache/EvalCacheMulti.scala +++ b/src/main/scala/evalCache/EvalCacheMulti.scala @@ -18,10 +18,10 @@ final private class EvalCacheMulti(using scheduler: org.apache.pekko.actor.typed.Scheduler ): import EvalCacheMulti.* - import EvalCacheUpgrade.{ EvalState, SetupId, SriString } + import EvalCacheUpgrade.{ EvalState, SriString } private val members = ConcurrentHashMap[SriString, WatchingMember](4096) - private val evals = ConcurrentHashMap[SetupId, EvalState](1024) + private val evals = ConcurrentHashMap[EvalCacheEntry.Id, EvalState](1024) private val expirableSris = ExpireCallbackMemo[Sri](scheduler, 1 minute, expire) private val upgradeMon = Monitor.evalCache.multi.upgrade @@ -36,15 +36,14 @@ final private class EvalCacheMulti(using WatchingMember(sri, e.variant, e.fens) ) .setups - .foreach: setupId => - evals.compute(setupId, (_, prev) => Option(prev).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri))) + .foreach: id => + evals.compute(id, (_, prev) => Option(prev).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri))) expirableSris.put(sri) def onEval(input: EvalCacheEntry.Input, fromSri: Sri): Unit = - val setupId = makeSetupId(input.situation.variant, input.fen) Option( evals.computeIfPresent( - setupId, + input.id, (_, ev) => if ev.depth >= input.eval.depth then ev else ev.copy(depth = input.eval.depth) @@ -63,9 +62,9 @@ final private class EvalCacheMulti(using Option(members.remove(sri.value)).foreach: _.setups.foreach(unregisterEval(_, sri)) - private def unregisterEval(setupId: SetupId, sri: Sri): Unit = + private def unregisterEval(id: EvalCacheEntry.Id, sri: Sri): Unit = evals.computeIfPresent( - setupId, + id, (_, eval) => val newSris = eval.sris - sri if newSris.isEmpty then null @@ -81,8 +80,5 @@ private object EvalCacheMulti: import EvalCacheUpgrade.* - def makeSetupId(variant: Variant, fen: Fen.Full): SetupId = - s"${variant.id}${SmallFen.make(variant, fen.simple)}" - case class WatchingMember(sri: Sri, variant: Variant, fens: List[Fen.Full]): - def setups: List[SetupId] = fens.map(makeSetupId(variant, _)) + def setups: List[EvalCacheEntry.Id] = fens.flatMap(EvalCacheEntry.Id.from(variant, _)) diff --git a/src/main/scala/evalCache/EvalCacheUpgrade.scala b/src/main/scala/evalCache/EvalCacheUpgrade.scala index 8033b74d..51da9ccc 100644 --- a/src/main/scala/evalCache/EvalCacheUpgrade.scala +++ b/src/main/scala/evalCache/EvalCacheUpgrade.scala @@ -1,8 +1,7 @@ package lila.ws package evalCache -import chess.format.{ Fen, UciPath } -import chess.variant.Variant +import chess.format.UciPath import play.api.libs.json.JsString import java.util.concurrent.ConcurrentHashMap @@ -28,20 +27,24 @@ final private class EvalCacheUpgrade(using private val upgradeMon = Monitor.evalCache.single.upgrade def register(sri: Sri, e: EvalGet): Unit = - members.compute( - sri.value, - (_, prev) => - Option(prev).foreach: member => - unregisterEval(member.setupId, sri) - val setupId = makeSetupId(e.variant, e.fen, e.multiPv) - evals.compute(setupId, (_, eval) => Option(eval).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri))) - WatchingMember(sri, setupId, e.path) - ) - expirableSris.put(sri) + EvalCacheEntry.Id + .from(e.variant, e.fen) + .foreach: entryId => + members.compute( + sri.value, + (_, prev) => + Option(prev).foreach: member => + unregisterEval(member.setupId, sri) + val setupId = SetupId(entryId, e.multiPv) + evals + .compute(setupId, (_, eval) => Option(eval).fold(EvalState(Set(sri), Depth(0)))(_.addSri(sri))) + WatchingMember(sri, setupId, e.path) + ) + expirableSris.put(sri) def onEval(input: EvalCacheEntry.Input, fromSri: Sri): Unit = (1 to input.eval.multiPv.value).foreach: multiPv => - val setupId = makeSetupId(input.situation.variant, input.fen, MultiPv(multiPv)) + val setupId = SetupId(input.id, MultiPv(multiPv)) Option( evals.computeIfPresent( setupId, @@ -82,12 +85,10 @@ final private class EvalCacheUpgrade(using private object EvalCacheUpgrade: type SriString = String - type SetupId = String + + case class SetupId(entryId: EvalCacheEntry.Id, multiPv: MultiPv) case class EvalState(sris: Set[Sri], depth: Depth): def addSri(sri: Sri) = copy(sris = sris + sri) - def makeSetupId(variant: Variant, fen: Fen.Full, multiPv: MultiPv): SetupId = - s"${variant.id}${SmallFen.make(variant, fen.simple)}^$multiPv" - case class WatchingMember(sri: Sri, setupId: SetupId, path: UciPath) diff --git a/src/main/scala/evalCache/package.scala b/src/main/scala/evalCache/package.scala index e8c4a176..e3d82f48 100644 --- a/src/main/scala/evalCache/package.scala +++ b/src/main/scala/evalCache/package.scala @@ -2,8 +2,7 @@ package lila.ws package evalCache import cats.data.NonEmptyList -import chess.format.{ Fen, Uci } -import chess.variant.Variant +import chess.format.Uci val MIN_KNODES = Knodes(3000) val MIN_DEPTH = Depth(20) @@ -26,15 +25,3 @@ object Moves extends TotalWrapper[Moves, NonEmptyList[Uci]]: opaque type Trust = Double object Trust extends OpaqueDouble[Trust]: extension (a: Trust) def isEnough = a > -1 - -opaque type SmallFen = String -object SmallFen extends OpaqueString[SmallFen]: - def make(variant: Variant, fen: Fen.Simple): SmallFen = - val base = fen.value.split(' ').take(4).mkString("").filter { c => - c != '/' && c != '-' && c != 'w' - } - if variant == chess.variant.ThreeCheck - then fen.value.split(' ').lift(6).foldLeft(base)(_ + _) - else base - def validate(variant: Variant, fen: Fen.Full): Option[SmallFen] = - Fen.read(variant, fen).exists(_.playable(false)).option(make(variant, fen.simple))