migration WIP

rm0193-mapreduce
Thibault Duplessis 2019-11-30 10:11:25 -06:00
parent 08ae65fb81
commit e0b39662c7
18 changed files with 176 additions and 172 deletions

View File

@ -136,7 +136,7 @@ lazy val search = module("search", Seq(common, hub)).settings(
)
lazy val chat = module("chat", Seq(common, db, user, security, i18n, socket)).settings(
libraryDependencies ++= provided(play.api, scalatags) ++ reactivemongo.bundle
libraryDependencies ++= provided(play.api, play.joda, scalatags) ++ reactivemongo.bundle
)
lazy val room = module("room", Seq(common, socket, chat)).settings(

View File

@ -492,7 +492,7 @@ challenge {
max_playing = ${setup.max_playing}
}
evalCache {
collection.eval_cache = eval_cache
collection.evalCache = eval_cache
}
irwin {
collection.report = irwin_report

View File

@ -87,6 +87,8 @@ object Chat {
case class Setup(id: Id, publicSource: PublicSource)
case class MaxLines(value: Int) extends AnyVal with IntValue
def tournamentSetup(tourId: String) = Setup(Id(tourId), PublicSource.Tournament(tourId))
def simulSetup(simulId: String) = Setup(Id(simulId), PublicSource.Simul(simulId))

View File

@ -5,22 +5,24 @@ import reactivemongo.api.ReadPreference
import scala.concurrent.duration._
import lila.db.dsl._
import lila.common.config.NetConfig
import lila.hub.actorApi.shutup.{ PublicSource, RecordPublicChat, RecordPrivateChat }
import lila.user.{ User, UserRepo }
final class ChatApi(
coll: Coll,
userRepo: UserRepo,
chatTimeout: ChatTimeout,
flood: lila.security.Flood,
spam: lila.security.Spam,
shutup: akka.actor.ActorSelection,
modLog: akka.actor.ActorSelection,
asyncCache: lila.memo.AsyncCache.Builder,
maxLinesPerChat: Int,
netDomain: String
maxLinesPerChat: Chat.MaxLines,
net: NetConfig
) {
import Chat.{ userChatBSONHandler, chatIdBSONHandler, classify }
import Chat.{ userChatBSONHandler, chatIdBSONHandler, chanOf }
object userChat {
@ -87,7 +89,7 @@ final class ChatApi(
}
}
def clear(chatId: Chat.Id) = coll.remove($id(chatId)).void
def clear(chatId: Chat.Id) = coll.delete.one($id(chatId)).void
def system(chatId: Chat.Id, text: String): Funit = {
val line = UserLine(systemUserId, None, text, troll = false, deleted = false)
@ -102,13 +104,13 @@ final class ChatApi(
}
def timeout(chatId: Chat.Id, modId: User.ID, userId: User.ID, reason: ChatTimeout.Reason, local: Boolean): Funit =
coll.byId[UserChat](chatId.value) zip UserRepo.byId(modId) zip UserRepo.byId(userId) flatMap {
coll.byId[UserChat](chatId.value) zip userRepo.byId(modId) zip userRepo.byId(userId) flatMap {
case Some(chat) ~ Some(mod) ~ Some(user) if isMod(mod) || local => doTimeout(chat, mod, user, reason)
case _ => fuccess(none)
}
def userModInfo(username: String): Fu[Option[UserModInfo]] =
UserRepo named username flatMap {
userRepo named username flatMap {
_ ?? { user =>
chatTimeout.history(user, 20) dmap { UserModInfo(user, _).some }
}
@ -123,7 +125,7 @@ final class ChatApi(
)
val c2 = c.markDeleted(user)
val chat = line.fold(c2)(c2.add)
coll.update($id(chat.id), chat).void >>
coll.update.one($id(chat.id), chat).void >>
chatTimeout.add(c, mod, user, reason) >>- {
cached invalidate chat.id
publish(chat.id, actorApi.OnTimeout(user.id))
@ -137,7 +139,7 @@ final class ChatApi(
def delete(c: UserChat, user: User): Funit = {
val chat = c.markDeleted(user)
coll.update($id(chat.id), chat).void >>- {
coll.update.one($id(chat.id), chat).void >>- {
cached invalidate chat.id
publish(chat.id, actorApi.OnTimeout(user.id))
}
@ -150,7 +152,7 @@ final class ChatApi(
}
private[ChatApi] def makeLine(chatId: Chat.Id, userId: String, t1: String): Fu[Option[UserLine]] =
UserRepo.speaker(userId) zip chatTimeout.isActive(chatId, userId) dmap {
userRepo.speaker(userId) zip chatTimeout.isActive(chatId, userId) dmap {
case (Some(user), false) if user.enabled => Writer cut t1 flatMap { t2 =>
(user.isBot || flood.allowMessage(userId, t2)) option {
if (~user.troll) lila.mon.chat.trollTrue()
@ -193,18 +195,18 @@ final class ChatApi(
}
private def publish(chatId: Chat.Id, msg: Any): Unit =
lila.common.Bus.publish(msg, classify(chatId))
lila.common.Bus.publish(msg, chanOf(chatId))
def remove(chatId: Chat.Id) = coll.remove($id(chatId)).void
def remove(chatId: Chat.Id) = coll.delete.one($id(chatId)).void
def removeAll(chatIds: List[Chat.Id]) = coll.remove($inIds(chatIds)).void
def removeAll(chatIds: List[Chat.Id]) = coll.delete.one($inIds(chatIds)).void
private def pushLine(chatId: Chat.Id, line: Line): Funit = coll.update(
private def pushLine(chatId: Chat.Id, line: Line): Funit = coll.update.one(
$id(chatId),
$doc("$push" -> $doc(
Chat.BSONFields.lines -> $doc(
"$each" -> List(line),
"$slice" -> -maxLinesPerChat
"$slice" -> -maxLinesPerChat.value
)
)),
upsert = true
@ -218,8 +220,8 @@ final class ChatApi(
def cut(text: String) = Some(text.trim take Line.textMaxSize) filter (_.nonEmpty)
private val gameUrlRegex = (Pattern.quote(netDomain) + """\b/(\w{8})\w{4}\b""").r
private val gameUrlReplace = Matcher.quoteReplacement(netDomain) + "/$1";
private val gameUrlRegex = (Pattern.quote(net.domain) + """\b/(\w{8})\w{4}\b""").r
private val gameUrlReplace = Matcher.quoteReplacement(net.domain) + "/$1";
private def noPrivateUrl(str: String): String = gameUrlRegex.replaceAllIn(str, gameUrlReplace)
private def noShouting(str: String): String = if (isShouting(str)) str.toLowerCase else str
private val multilineRegex = """\n\n{2,}+""".r

View File

@ -66,13 +66,13 @@ object ChatTimeout {
case object Insult extends Reason("insult", "disrespecting other players")
case object Spam extends Reason("spam", "spamming the chat")
case object Other extends Reason("other", "inappropriate behavior")
val all = List(PublicShaming, Insult, Spam, Other)
val all: List[Reason] = List(PublicShaming, Insult, Spam, Other)
def apply(key: String) = all.find(_.key == key)
}
implicit val ReasonBSONHandler: BSONHandler[BSONString, Reason] = new BSONHandler[BSONString, Reason] {
def read(b: BSONString) = Reason(b.value) err s"Invalid reason ${b.value}"
def write(x: Reason) = BSONString(x.key)
}
implicit val ReasonBSONHandler: BSONHandler[Reason] = lila.db.BSON.tryHandler[Reason](
{ case BSONString(value) => Reason(value) toTry s"Invalid reason ${value}" },
x => BSONString(x.key)
)
case class Reinstate(_id: String, chat: String, user: String)
implicit val ReinstateBSONReader: BSONDocumentReader[Reinstate] = Macros.reader[Reinstate]

View File

@ -1,67 +1,59 @@
package lila.chat
import akka.actor.{ ActorSystem, Props, ActorSelection }
import com.typesafe.config.Config
import com.softwaremill.macwire._
import io.methvin.play.autoconfig._
import play.api.Configuration
import scala.concurrent.duration.FiniteDuration
import lila.common.config._
private case class ChatConfig(
@ConfigName("collection.chat") chatColl: CollName,
@ConfigName("collection.timeout") timeoutColl: CollName,
@ConfigName("max_lines") maxLines: Chat.MaxLines,
@ConfigName("actor.name") actorName: String,
net: NetConfig,
@ConfigName("timeout.duration") timeoutDuration: FiniteDuration,
@ConfigName("timeout.check_every") timeoutCheckEvery: FiniteDuration
)
final class Env(
config: Config,
appConfig: Configuration,
userRepo: lila.user.UserRepo,
db: lila.db.Env,
flood: lila.security.Flood,
spam: lila.security.Spam,
shutup: ActorSelection,
modLog: ActorSelection,
asyncCache: lila.memo.AsyncCache.Builder,
system: ActorSystem
) {
asyncCache: lila.memo.AsyncCache.Builder
)(implicit system: ActorSystem) {
private val settings = new {
val CollectionChat = config getString "collection.chat"
val CollectionTimeout = config getString "collection.timeout"
val MaxLinesPerChat = config getInt "max_lines"
val NetDomain = config getString "net.domain"
val ActorName = config getString "actor.name"
val TimeoutDuration = config duration "timeout.duration"
val TimeoutCheckEvery = config duration "timeout.check_every"
}
import settings._
private implicit val maxPerLineLoader = intLoader(Chat.MaxLines.apply)
private val config = appConfig.get[ChatConfig]("chat")(AutoConfig.loader)
import config._
val timeout = new ChatTimeout(
coll = timeoutColl,
duration = TimeoutDuration
coll = db(timeoutColl),
duration = timeoutDuration
)
val api = new ChatApi(
coll = chatColl,
coll = db(chatColl),
userRepo = userRepo,
chatTimeout = timeout,
flood = flood,
spam = spam,
shutup = shutup,
modLog = modLog,
asyncCache = asyncCache,
maxLinesPerChat = MaxLinesPerChat,
netDomain = NetDomain
maxLinesPerChat = maxLines,
net = net
)
val panic = new ChatPanic
val panic = wire[ChatPanic]
system.scheduler.schedule(TimeoutCheckEvery, TimeoutCheckEvery) {
timeout.checkExpired foreach api.userChat.reinstate
system.scheduler.scheduleWithFixedDelay(timeoutCheckEvery, timeoutCheckEvery) {
() => timeout.checkExpired foreach api.userChat.reinstate
}
private[chat] lazy val chatColl = db(CollectionChat)
private[chat] lazy val timeoutColl = db(CollectionTimeout)
}
object Env {
lazy val current: Env = "chat" boot new Env(
config = lila.common.PlayApp loadConfig "chat",
db = lila.db.Env.current,
flood = lila.security.Env.current.flood,
spam = lila.security.Env.current.spam,
shutup = lila.hub.Env.current.shutup,
modLog = lila.hub.Env.current.mod,
asyncCache = lila.memo.Env.current.asyncCache,
system = lila.common.PlayApp.system
)
}

View File

@ -3,9 +3,14 @@ package lila.chat
import lila.common.LightUser
import lila.common.PimpedJson._
import play.api.libs.json._
import play.api.libs.json.JodaWrites._
object JsonView {
import writers._
lazy val timeoutReasons = Json toJson ChatTimeout.Reason.all
def apply(chat: AnyChat): JsValue = chat match {
case c: MixedChat => mixedChatWriter writes c
case c: UserChat => userChatWriter writes c
@ -23,46 +28,48 @@ object JsonView {
"writeable" -> writeable
)
implicit val chatIdWrites: Writes[Chat.Id] = stringIsoWriter(Chat.chatIdIso)
object writers {
lazy val timeoutReasons = Json toJson ChatTimeout.Reason.all
implicit val chatIdWrites: Writes[Chat.Id] = stringIsoWriter(Chat.chatIdIso)
implicit val timeoutReasonWriter: Writes[ChatTimeout.Reason] = OWrites[ChatTimeout.Reason] { r =>
Json.obj("key" -> r.key, "name" -> r.name)
}
implicit val timeoutReasonWriter: Writes[ChatTimeout.Reason] = OWrites[ChatTimeout.Reason] { r =>
Json.obj("key" -> r.key, "name" -> r.name)
}
implicit def timeoutEntryWriter(implicit lightUser: LightUser.GetterSync) = OWrites[ChatTimeout.UserEntry] { e =>
Json.obj(
"reason" -> e.reason.key,
"mod" -> lightUser(e.mod).fold("?")(_.name),
"date" -> e.createdAt
)
}
implicit def timeoutEntryWriter(implicit lightUser: LightUser.GetterSync): OWrites[ChatTimeout.UserEntry] =
OWrites[ChatTimeout.UserEntry] { e =>
Json.obj(
"reason" -> e.reason.key,
"mod" -> lightUser(e.mod).fold("?")(_.name),
"date" -> e.createdAt
)
}
implicit val mixedChatWriter: Writes[MixedChat] = Writes[MixedChat] { c =>
JsArray(c.lines map lineWriter.writes)
}
implicit val mixedChatWriter: Writes[MixedChat] = Writes[MixedChat] { c =>
JsArray(c.lines map lineWriter.writes)
}
implicit val userChatWriter: Writes[UserChat] = Writes[UserChat] { c =>
JsArray(c.lines map userLineWriter.writes)
}
implicit val userChatWriter: Writes[UserChat] = Writes[UserChat] { c =>
JsArray(c.lines map userLineWriter.writes)
}
private[chat] implicit val lineWriter: OWrites[Line] = OWrites[Line] {
case l: UserLine => userLineWriter writes l
case l: PlayerLine => playerLineWriter writes l
}
private[chat] implicit val lineWriter: OWrites[Line] = OWrites[Line] {
case l: UserLine => userLineWriter writes l
case l: PlayerLine => playerLineWriter writes l
}
private implicit val userLineWriter = OWrites[UserLine] { l =>
Json.obj(
"u" -> l.username,
"t" -> l.text
).add("r" -> l.troll).add("d" -> l.deleted).add("title" -> l.title)
}
private implicit val userLineWriter = OWrites[UserLine] { l =>
Json.obj(
"u" -> l.username,
"t" -> l.text
).add("r" -> l.troll).add("d" -> l.deleted).add("title" -> l.title)
}
private implicit val playerLineWriter = OWrites[PlayerLine] { l =>
Json.obj(
"c" -> l.color.name,
"t" -> l.text
)
private implicit val playerLineWriter = OWrites[PlayerLine] { l =>
Json.obj(
"c" -> l.color.name,
"t" -> l.text
)
}
}
}

View File

@ -46,15 +46,15 @@ object Line {
private val invalidLine = UserLine("", None, "[invalid character]", troll = false, deleted = true)
private[chat] implicit val userLineBSONHandler = new BSONHandler[BSONString, UserLine] {
def read(bsonStr: BSONString) = strToUserLine(bsonStr.value) getOrElse invalidLine
def write(x: UserLine) = BSONString(userLineToStr(x))
}
private[chat] implicit val userLineBSONHandler = lila.db.BSON.quickHandler[UserLine](
{ case BSONString(value) => strToUserLine(value) getOrElse invalidLine },
x => BSONString(userLineToStr(x))
)
private[chat] implicit val lineBSONHandler = new BSONHandler[BSONString, Line] {
def read(bsonStr: BSONString) = strToLine(bsonStr.value) getOrElse invalidLine
def write(x: Line) = BSONString(lineToStr(x))
}
private[chat] implicit val lineBSONHandler = lila.db.BSON.quickHandler[Line](
{ case BSONString(value) => strToLine(value) getOrElse invalidLine },
x => BSONString(lineToStr(x))
)
private val UserLineRegex = """(?s)([\w-~]{2,}+)([ !?])(.++)""".r
private def strToUserLine(str: String): Option[UserLine] = str match {

View File

@ -28,9 +28,11 @@ final class PimpedOption[A](private val self: Option[A]) extends AnyVal {
def toFailure[B](b: => B): scalaz.Validation[A, B] = o.toFailure(self)(b)
def toTry(err: => Exception): Try[A] =
def toTryWith(err: => Exception): Try[A] =
self.fold[Try[A]](scala.util.Failure(err))(scala.util.Success.apply)
def toTry(err: => String): Try[A] = toTryWith(lila.base.LilaException(err))
def err(message: => String): A = self.getOrElse(sys.error(message))
def ifNone(n: => Unit): Unit = if (self.isEmpty) n

View File

@ -27,6 +27,6 @@ object config {
implicit val emailAddressLoader = strLoader(EmailAddress.apply)
implicit val netLoader = AutoConfig.loader[NetConfig]
private def strLoader[A](f: String => A): ConfigLoader[A] = ConfigLoader(_.getString) map f
private def intLoader[A](f: Int => A): ConfigLoader[A] = ConfigLoader(_.getInt) map f
def strLoader[A](f: String => A): ConfigLoader[A] = ConfigLoader(_.getString) map f
def intLoader[A](f: Int => A): ConfigLoader[A] = ConfigLoader(_.getInt) map f
}

View File

@ -3,8 +3,8 @@ package lila.db
import org.joda.time.DateTime
import ornicar.scalalib.Zero
import reactivemongo.api.bson._
import reactivemongo.api.bson.exceptions.TypeDoesNotMatchException
import reactivemongo.api.bson.compat._
import reactivemongo.api.bson.exceptions.TypeDoesNotMatchException
import scala.util.{ Try, Success, Failure }
import dsl._
@ -108,7 +108,7 @@ object BSON extends Handlers {
def quickHandler[T](read: PartialFunction[BSONValue, T], write: T => BSONValue): BSONHandler[T] = new BSONHandler[T] {
def readTry(bson: BSONValue) = read.andThen(Success(_)).applyOrElse(
bson,
(b: BSONValue) => Failure(TypeDoesNotMatchException("BSONBinary", b.getClass.getSimpleName))
(b: BSONValue) => handlerBadType(b)
)
def writeTry(t: T) = Success(write(t))
}
@ -116,11 +116,17 @@ object BSON extends Handlers {
def tryHandler[T](read: PartialFunction[BSONValue, Try[T]], write: T => BSONValue): BSONHandler[T] = new BSONHandler[T] {
def readTry(bson: BSONValue) = read.applyOrElse(
bson,
(b: BSONValue) => Failure(TypeDoesNotMatchException("BSONBinary", b.getClass.getSimpleName))
(b: BSONValue) => handlerBadType(b)
)
def writeTry(t: T) = Success(write(t))
}
def handlerBadType[T](b: BSONValue): Try[T] =
Failure(TypeDoesNotMatchException("BSONBinary", b.getClass.getSimpleName))
def handlerBadValue[T](msg: String): Try[T] =
Failure(new IllegalArgumentException(msg))
final class Reader(val doc: Bdoc) {
val map = {

View File

@ -3,7 +3,6 @@ package lila.db
import scala.util.{ Try, Success, Failure }
import reactivemongo.api.bson._
import reactivemongo.api.bson.exceptions.TypeDoesNotMatchException
case class ByteArray(value: Array[Byte]) {

View File

@ -2,7 +2,6 @@ package lila.db
import org.joda.time.DateTime
import reactivemongo.api.bson._
import reactivemongo.api.bson.exceptions.TypeDoesNotMatchException
import scala.util.{ Try, Success, Failure }
import scalaz.NonEmptyList

View File

@ -1,6 +1,7 @@
package lila.evalCache
import reactivemongo.api.bson._
import scala.util.{ Try, Success, Failure }
import scalaz.NonEmptyList
import chess.format.Uci
@ -14,7 +15,7 @@ private object BSONHandlers {
private implicit val TrustBSONHandler = doubleAnyValHandler[Trust](_.value, Trust.apply)
private implicit val KnodesBSONHandler = intAnyValHandler[Knodes](_.value, Knodes.apply)
implicit val PvsHandler = new BSONHandler[BSONString, NonEmptyList[Pv]] {
implicit val PvsHandler = new BSONHandler[NonEmptyList[Pv]] {
private def scoreWrite(s: Score): String = s.value.fold(_.value.toString, m => s"#${m.value}")
private def scoreRead(str: String): Option[Score] =
if (str startsWith "#") str.drop(1).toIntOption map { m => Score mate Mate(m) }
@ -25,36 +26,46 @@ private object BSONHandlers {
private val scoreSeparator = ':'
private val pvSeparator = '/'
private val pvSeparatorStr = pvSeparator.toString
def read(bs: BSONString): NonEmptyList[Pv] = bs.value.split(pvSeparator).toList.map { pvStr =>
pvStr.split(scoreSeparator) match {
case Array(score, moves) => Pv(
scoreRead(score) err s"Invalid score $score",
movesRead(moves) err s"Invalid moves $moves"
)
case x => sys error s"Invalid PV $pvStr: ${x.toList} (in ${bs.value})"
def readTry(bs: BSONValue) = bs match {
case BSONString(value) => Try {
value.split(pvSeparator).toList.map { pvStr =>
pvStr.split(scoreSeparator) match {
case Array(score, moves) => Pv(
scoreRead(score) err s"Invalid score $score",
movesRead(moves) err s"Invalid moves $moves"
)
case x => sys error s"Invalid PV $pvStr: ${x.toList} (in ${value})"
}
}
}.flatMap {
_.toNel toTry lila.base.LilaException(s"Empty PVs ${value}")
}
}.toNel err s"Empty PVs ${bs.value}"
def write(x: NonEmptyList[Pv]) = BSONString {
case b => lila.db.BSON.handlerBadType[NonEmptyList[Pv]](b)
}
def writeTry(x: NonEmptyList[Pv]) = Success(BSONString {
x.toList.map { pv =>
s"${scoreWrite(pv.score)}$scoreSeparator${movesWrite(pv.moves)}"
} mkString pvSeparatorStr
}
})
}
implicit val EntryIdHandler = new BSONHandler[BSONString, Id] {
def read(bs: BSONString): Id = bs.value split ':' match {
case Array(fen) => Id(chess.variant.Standard, SmallFen raw fen)
case Array(variantId, fen) => Id(
variantId.toIntOption flatMap chess.variant.Variant.apply err s"Invalid evalcache variant $variantId",
SmallFen raw fen
)
case _ => sys error s"Invalid evalcache id ${bs.value}"
}
def write(x: Id) = BSONString {
implicit val EntryIdHandler = lila.db.BSON.tryHandler[Id](
{
case BSONString(value) =>
value split ':' match {
case Array(fen) => Success(Id(chess.variant.Standard, SmallFen raw fen))
case Array(variantId, fen) => Success(Id(
variantId.toIntOption flatMap chess.variant.Variant.apply err s"Invalid evalcache variant $variantId",
SmallFen raw fen
))
case _ => lila.db.BSON.handlerBadValue(s"Invalid evalcache id ${value}")
}
},
x => BSONString {
if (x.variant.standard || x.variant == chess.variant.FromPosition) x.smallFen.value
else s"${x.variant.id}:${x.smallFen.value}"
}
}
)
implicit val evalHandler = Macros.handler[Eval]
implicit val entryHandler = Macros.handler[EvalCacheEntry]

View File

@ -1,38 +1,32 @@
package lila.evalCache
import com.typesafe.config.Config
import com.softwaremill.macwire._
import play.api.Configuration
import play.api.libs.json.JsValue
import scala.concurrent.duration._
import lila.hub.actorApi.socket.remote.{ TellSriIn, TellSriOut }
import lila.common.Bus
import lila.common.config.CollName
import lila.hub.actorApi.socket.remote.{ TellSriIn, TellSriOut }
import lila.socket.Socket.Sri
final class Env(
config: Config,
appConfig: Configuration,
userRepo: lila.user.UserRepo,
settingStore: lila.memo.SettingStore.Builder,
db: lila.db.Env,
asyncCache: lila.memo.AsyncCache.Builder
) {
private val CollectionEvalCache = config getString "collection.eval_cache"
private lazy val coll = db(appConfig.get[CollName]("evalCache.collection.evalCache"))
private lazy val truster = new EvalCacheTruster(asyncCache)
private lazy val truster = wire[EvalCacheTruster]
private lazy val upgrade = new EvalCacheUpgrade
private lazy val upgrade = wire[EvalCacheUpgrade]
lazy val api = new EvalCacheApi(
coll = db(CollectionEvalCache),
truster = truster,
upgrade = upgrade,
asyncCache = asyncCache
)
lazy val api: EvalCacheApi = wire[EvalCacheApi]
private lazy val socketHandler = new EvalCacheSocketHandler(
api = api,
truster = truster,
upgrade = upgrade
)
private lazy val socketHandler = wire[EvalCacheSocketHandler]
// remote socket support
Bus.subscribeFun("remoteSocketIn:evalGet") {
@ -55,13 +49,3 @@ final class Env(
}
}
}
object Env {
lazy val current: Env = "evalCache" boot new Env(
config = lila.common.PlayApp loadConfig "evalCache",
settingStore = lila.memo.Env.current.settingStore,
db = lila.db.Env.current,
asyncCache = lila.memo.Env.current.asyncCache
)
}

View File

@ -42,7 +42,7 @@ final class EvalCacheApi(
private[evalCache] def drop(variant: Variant, fen: FEN): Funit = {
val id = Id(chess.variant.Standard, SmallFen.make(variant, fen))
coll.remove($id(id)).void >>- cache.put(id, none)
coll.delete.one($id(id)).void >>- cache.put(id, none)
}
private val cache = asyncCache.multi[Id, Option[EvalCacheEntry]](
@ -58,7 +58,7 @@ final class EvalCacheApi(
private def getEntry(id: Id): Fu[Option[EvalCacheEntry]] = cache get id
private def fetchAndSetAccess(id: Id): Fu[Option[EvalCacheEntry]] =
coll.find($id(id)).one[EvalCacheEntry] addEffect { res =>
coll.ext.find($id(id)).one[EvalCacheEntry] addEffect { res =>
if (res.isDefined) coll.updateFieldUnchecked($id(id), "usedAt", DateTime.now)
}
@ -74,13 +74,13 @@ final class EvalCacheApi(
evals = List(input.eval),
usedAt = DateTime.now
)
coll.insert(entry).recover(lila.db.recoverDuplicateKey(_ => ())) >>-
coll.insert.one(entry).recover(lila.db.recoverDuplicateKey(_ => ())) >>-
cache.put(input.id, entry.some) >>-
upgrade.onEval(input, sri)
case Some(oldEntry) =>
val entry = oldEntry add input.eval
!(entry similarTo oldEntry) ?? {
coll.update($id(entry.id), entry, upsert = true).void >>-
coll.update.one($id(entry.id), entry, upsert = true).void >>-
cache.put(input.id, entry.some) >>-
upgrade.onEval(input, sri)
}

View File

@ -1,12 +1,15 @@
package lila.evalCache
import scala.concurrent.duration._
import org.joda.time.{ DateTime, Days }
import scala.concurrent.duration._
import lila.security.Granter
import lila.user.{ User, UserRepo }
private final class EvalCacheTruster(asyncCache: lila.memo.AsyncCache.Builder) {
private final class EvalCacheTruster(
asyncCache: lila.memo.AsyncCache.Builder,
userRepo: UserRepo
) {
import EvalCacheEntry.{ Trust, TrustedUser }
@ -25,7 +28,7 @@ private final class EvalCacheTruster(asyncCache: lila.memo.AsyncCache.Builder) {
private val userIdCache = asyncCache.multi[User.ID, Option[TrustedUser]](
name = "evalCache.userIdTrustCache ",
f = userId => UserRepo named userId map2 makeTrusted,
f = userId => userRepo named userId map2 makeTrusted,
expireAfter = _.ExpireAfterWrite(10 minutes),
resultTimeout = 10 seconds
)

View File

@ -59,10 +59,7 @@ object OAuthScope {
import reactivemongo.api.bson._
import lila.db.dsl._
private[oauth] implicit val scopeHandler = lila.db.BSON.tryHandler[OAuthScope](
{
case b: BSONString => OAuthScope.byKey.get(b.value) toTry
lila.base.LilaException(s"No such scope: ${b.value}")
},
{ case b: BSONString => OAuthScope.byKey.get(b.value) toTry s"No such scope: ${b.value}" },
s => BSONString(s.key)
)
}