periodic cache WIP

periodic-cache
Thibault Duplessis 2019-08-17 13:59:04 +02:00
parent 81d2d864b8
commit d8997b7e47
8 changed files with 52 additions and 20 deletions

View File

@ -150,8 +150,8 @@ object User extends LilaController {
val max = 50
negotiate(
html = notFoundJson(),
api = _ => env.cached.getTop50Online map { list =>
Ok(Json.toJson(list.take(getInt("nb", req).fold(10)(_ min max)).map(env.jsonView(_))))
api = _ => fuccess {
Ok(Json.toJson(env.cached.getTop50Online.take(getInt("nb", req).fold(10)(_ min max)).map(env.jsonView(_))))
}
)
}
@ -202,11 +202,10 @@ object User extends LilaController {
nbAllTime env.cached topNbGame nb
nbDay fuccess(Nil)
tourneyWinners Env.tournament.winners.all.map(_.top)
online env.cached.getTop50Online
_ <- Env.user.lightUserApi preloadMany tourneyWinners.map(_.userId)
} yield Ok(html.user.list(
tourneyWinners = tourneyWinners,
online = online,
online = env.cached.getTop50Online,
leaderboards = leaderboards,
nbDay = nbDay,
nbAllTime = nbAllTime

View File

@ -160,6 +160,4 @@ trait ScalatagsExtensions {
}
def titleOrText(v: String)(implicit ctx: Context): Modifier = titleOrText(ctx.blind, v)
// implicit val LilaModifierZero: Zero[Modifier] = Zero.instance(emptyModifier)
}

View File

@ -7,6 +7,7 @@ import akka.actor._
object ResilientScheduler {
private case object Tick
private case object Done
def apply(
every: FiniteDuration,
@ -17,10 +18,7 @@ object ResilientScheduler {
system.actorOf(Props(new Actor {
override def preStart: Unit = {
context setReceiveTimeout (atMost + 2.second)
scheduleNext
}
override def preStart: Unit = scheduleNext
def scheduleNext = context.system.scheduler.scheduleOnce(every, self, Tick)
@ -31,7 +29,13 @@ object ResilientScheduler {
logger error msg
throw new RuntimeException(msg)
case Tick => f >>- scheduleNext
case Tick =>
context setReceiveTimeout (atMost + 2.second)
f >>- { self ! Done }
case Done =>
if (every > atMost) context.setReceiveTimeout(Duration.Undefined)
scheduleNext
}
}))
}

View File

@ -61,7 +61,7 @@ object JsDump {
case literal: Simple => List(k -> JsString(literal.message))
case literal: Escaped => List(k -> JsString(literal.message))
case plurals: Plurals => plurals.messages.map {
case (quantity, msg) => k + quantitySuffix(quantity) -> JsString(msg)
case (quantity, msg) => s"$k${quantitySuffix(quantity)}" -> JsString(msg)
}
}

View File

@ -42,7 +42,7 @@ final class Env(
tournamentApi.allCurrentLeadersInStandard flatMap api.requests.fromTournamentLeaders
}
scheduler.future(15 minutes, "irwin leaderboards") {
userCache.getTop50Online flatMap api.requests.fromLeaderboard
api.requests fromLeaderboard userCache.getTop50Online
}
}

View File

@ -200,7 +200,7 @@ private object LobbyTrouper {
every = broomPeriod,
atMost = 10 seconds,
system = system,
logger = logger
logger = logger branch "trouper.broom"
) {
trouper.ask[Unit](Tick)
}

View File

@ -0,0 +1,30 @@
package lila.memo
import akka.actor.ActorSystem
import scala.concurrent.duration.FiniteDuration
final class PeriodicRefreshCache[A](
every: FiniteDuration,
atMost: FiniteDuration,
f: () => Fu[A],
default: A,
logger: lila.log.Logger
)(implicit system: ActorSystem) {
def get: A = cache
private var cache: A = default
system.scheduler.scheduleOnce(every) {
lila.common.ResilientScheduler(
every = every,
atMost = atMost,
system = system,
logger = logger
) {
f() map { a =>
cache = a
}
}
}
}

View File

@ -87,13 +87,14 @@ final class Cached(
keyToString = _.toString
)
private val top50Online = asyncCache.single[List[User]](
name = "user.top50online",
f = UserRepo.byIdsSortRatingNoBot(onlineUserIdMemo.keys, 50),
expireAfter = _.ExpireAfterWrite(10 seconds)
private val top50OnlineCache = new lila.memo.PeriodicRefreshCache[List[User]](
every = 30 seconds,
atMost = 15 seconds,
f = () => UserRepo.byIdsSortRatingNoBot(onlineUserIdMemo.keys, 50),
default = Nil,
logger = logger branch "top50online"
)
def getTop50Online = top50Online.get.nevermind
def getTop50Online = top50OnlineCache.get
object ranking {