Skip to content

Commit

Permalink
use normalized BinaryFen as evalCache id (#15020)
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasf committed Apr 7, 2024
1 parent 833148c commit 9fc0c1a
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 49 deletions.
30 changes: 5 additions & 25 deletions modules/evalCache/src/main/BSONHandlers.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package lila.evalCache

import chess.format.Uci
import chess.format.{ BinaryFen, Uci }
import reactivemongo.api.bson.*

import scala.util.{ Success, Try }
Expand Down Expand Up @@ -41,31 +41,11 @@ private object BSONHandlers:
}
case b => lila.db.BSON.handlerBadType[NonEmptyList[Pv]](b)

given BSONHandler[Id] = tryHandler[Id](
{ case BSONString(value) =>
value.split(':') match
case Array(fen) => Success(Id(chess.variant.Standard, SmallFen(fen)))
case Array(variantId, fen) =>
import chess.variant.Variant
Success(
Id(
Variant.Id
.from(variantId.toIntOption)
.flatMap {
Variant(_)
}
.err(s"Invalid evalcache variant $variantId"),
SmallFen(fen)
)
)
case _ => lila.db.BSON.handlerBadValue(s"Invalid evalcache id $value")
},
x =>
BSONString {
if x.variant.standard || x.variant.fromPosition then x.smallFen.value
else s"${x.variant.id}:${x.smallFen.value}"
}
given BSONHandler[BinaryFen] = lila.db.dsl.quickHandler[BinaryFen](
{ case v: BSONBinary => BinaryFen(v.byteArray) },
v => BSONBinary(v.value, Subtype.GenericBinarySubtype)
)
given BSONHandler[Id] = Macros.handler

given BSONDocumentReader[CloudEval] = Macros.reader
given BSONDocumentReader[EvalCacheEntry] = Macros.reader
2 changes: 1 addition & 1 deletion modules/evalCache/src/main/Env.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class Env(
cacheApi: lila.memo.CacheApi
)(using Executor, Scheduler, play.api.Mode):

private lazy val coll = yoloDb(CollName("eval_cache")).failingSilently()
private lazy val coll = yoloDb(CollName("eval_cache2")).failingSilently()

lazy val api: EvalCacheApi = wire[EvalCacheApi]

Expand Down
19 changes: 12 additions & 7 deletions modules/evalCache/src/main/EvalCacheApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ final class EvalCacheApi(coll: AsyncCollFailingSilently, cacheApi: lila.memo.Cac
import BSONHandlers.given

def getEvalJson(variant: Variant, fen: Fen.Full, multiPv: MultiPv): Fu[Option[JsObject]] =
getEval(Id(variant, SmallFen.make(variant, fen.simple)), multiPv)
.map:
_.map { JsonView.writeEval(_, fen) }
.addEffect(monitorRequest(fen))
Id.from(variant, fen)
.so: id =>
getEval(id, multiPv)
.map:
_.map { JsonView.writeEval(_, fen) }
.addEffect(monitorRequest(fen))

val getSinglePvEval: CloudEval.GetSinglePvEval = (variant, fen) =>
getEval(Id(variant, SmallFen.make(variant, fen.simple)), MultiPv(1))
Id.from(variant, fen)
.so: id =>
getEval(id, MultiPv(1))

private def monitorRequest(fen: Fen.Full)(res: Option[Any]) =
Fen
Expand All @@ -29,8 +33,9 @@ final class EvalCacheApi(coll: AsyncCollFailingSilently, cacheApi: lila.memo.Cac
lila.mon.evalCache.request(ply.value, res.isDefined).increment()

private[evalCache] def drop(variant: Variant, fen: Fen.Full): Funit =
val id = Id(variant, SmallFen.make(variant, fen.simple))
coll(_.delete.one($id(id)).void)
Id.from(variant, fen)
.so: id =>
coll(_.delete.one($id(id)).void)

private def getEval(id: Id, multiPv: MultiPv): Fu[Option[CloudEval]] =
cache.get(id).map(_.flatMap(_.makeBestMultiPvEval(multiPv)))
Expand Down
25 changes: 23 additions & 2 deletions modules/evalCache/src/main/EvalCacheEntry.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package lila.evalCache

import chess.variant.Variant
import chess.format.{ BinaryFen, Fen }
import chess.{ FullMoveNumber, HalfMoveClock, Situation }
import chess.variant.{ Chess960, FromPosition, Standard, Variant }

import lila.tree.CloudEval

Expand All @@ -22,4 +24,23 @@ case class EvalCacheEntry(

object EvalCacheEntry:

case class Id(variant: Variant, smallFen: SmallFen)
case class Id(position: BinaryFen)

object Id:
private def normalize(situation: Situation): Id =
Id(
BinaryFen.write(
Situation.AndFullMoveNumber(
situation
.withHistory(situation.history.setHalfMoveClock(HalfMoveClock.initial))
.withVariant(situation.variant match
case Standard | Chess960 | FromPosition => Standard
case other => other
),
FullMoveNumber.initial
)
)
)

def from(variant: Variant, fen: Fen.Full): Option[Id] =
Fen.read(variant, fen).map(normalize)
14 changes: 0 additions & 14 deletions modules/evalCache/src/main/package.scala
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
package lila.evalCache

import chess.format.{ Fen, Uci }
import chess.variant.Variant

export lila.core.lilaism.Lilaism.{ *, given }
export lila.common.extensions.*
import lila.tree.CloudEval

extension (e: CloudEval)
def multiPv = MultiPv(e.pvs.size)
def takePvs(multiPv: MultiPv) =
e.copy(pvs = NonEmptyList(e.pvs.head, e.pvs.tail.take(e.multiPv.value - 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'
}
variant match
case chess.variant.ThreeCheck => base + ~fen.value.split(' ').lift(6)
case _ => base

0 comments on commit 9fc0c1a

Please sign in to comment.