make leaderboard caches easier on memory

pull/1431/head
Thibault Duplessis 2016-01-11 09:07:45 +07:00
parent 4ff0ea41a0
commit 890f5b5195
6 changed files with 49 additions and 49 deletions

View File

@ -139,11 +139,11 @@ object User extends LilaController {
antichess <- env.cached top10Perf PerfType.Antichess.key
atomic <- env.cached top10Perf PerfType.Atomic.key
horde <- env.cached top10Perf PerfType.Horde.key
nbAllTime env.cached topNbGame nb map2 { (user: UserModel) =>
user -> user.count.game
}
nbDay Env.game.cached activePlayerUidsDay nb flatMap { pairs =>
UserRepo.byOrderedIds(pairs.map(_.userId)) map (_ zip pairs.map(_.nb))
nbAllTime env.cached topNbGame nb
nbDay Env.game.cached activePlayerUidsDay nb map {
_ flatMap { pair =>
env lightUser pair.userId map { UserModel.LightCount(_, pair.nb) }
}
}
tourneyWinners Env.tournament.winners scheduled nb
online env.cached topOnline 50
@ -163,9 +163,15 @@ object User extends LilaController {
nbDay = nbDay,
nbAllTime = nbAllTime))),
api = _ => fuccess {
implicit val userWrites = play.api.libs.json.Writes[UserModel] { env.jsonView(_, true) }
implicit val lightPerfWrites = play.api.libs.json.Writes[UserModel.LightPerf] { l =>
Json.obj(
"id" -> l.user.id,
"username" -> l.user.name,
"title" -> l.user.title,
"perfs" -> Json.obj(
l.perfKey -> Json.obj("rating" -> l.rating, "progress" -> l.progress)))
}
Ok(Json.obj(
"online" -> online,
"bullet" -> bullet,
"blitz" -> blitz,
"classical" -> classical,

View File

@ -16,7 +16,7 @@ import play.api.libs.json._
final class Preload(
tv: Tv,
leaderboard: Boolean => Fu[List[(User, PerfType)]],
leaderboard: Boolean => Fu[List[User.LightPerf]],
tourneyWinners: Int => Fu[List[Winner]],
timelineEntries: String => Fu[List[Entry]],
streamsOnAir: () => Fu[List[StreamOnAir]],
@ -26,7 +26,7 @@ final class Preload(
getPlayban: String => Fu[Option[TempBan]],
lightUser: String => Option[LightUser]) {
private type Response = (JsObject, List[Entry], List[MiniForumPost], List[Tournament], List[Simul], Option[Game], List[(User, PerfType)], List[Winner], Option[lila.puzzle.DailyPuzzle], List[StreamOnAir], List[lila.blog.MiniPost], Option[TempBan], Option[Preload.CurrentGame], Int)
private type Response = (JsObject, List[Entry], List[MiniForumPost], List[Tournament], List[Simul], Option[Game], List[User.LightPerf], List[Winner], Option[lila.puzzle.DailyPuzzle], List[StreamOnAir], List[lila.blog.MiniPost], Option[TempBan], Option[Preload.CurrentGame], Int)
def apply(
posts: Fu[List[MiniForumPost]],

View File

@ -1,4 +1,4 @@
@(data: play.api.libs.json.JsObject, userTimeline: List[lila.timeline.Entry], forumRecent: List[lila.forum.MiniForumPost], tours: List[Tournament], simuls: List[lila.simul.Simul], featured: Option[Game], leaderboard: List[(User, lila.rating.PerfType)], tournamentWinners: List[lila.tournament.Winner], puzzle: Option[lila.puzzle.DailyPuzzle], streams: List[lila.tv.StreamOnAir], lastPost: List[lila.blog.MiniPost], playban: Option[lila.playban.TempBan], currentGame: Option[lila.app.mashup.Preload.CurrentGame], nbRounds: Int)(implicit ctx: Context)
@(data: play.api.libs.json.JsObject, userTimeline: List[lila.timeline.Entry], forumRecent: List[lila.forum.MiniForumPost], tours: List[Tournament], simuls: List[lila.simul.Simul], featured: Option[Game], leaderboard: List[User.LightPerf], tournamentWinners: List[lila.tournament.Winner], puzzle: Option[lila.puzzle.DailyPuzzle], streams: List[lila.tv.StreamOnAir], lastPost: List[lila.blog.MiniPost], playban: Option[lila.playban.TempBan], currentGame: Option[lila.app.mashup.Preload.CurrentGame], nbRounds: Int)(implicit ctx: Context)
@underchat = {
<div id="featured_game">
@ -140,15 +140,15 @@ description = trans.freeOnlineChessGamePlayChessNowInACleanInterfaceNoRegistrati
<div class="undertable_inner scroll-shadow-hard">
<table>
<tbody>
@leaderboard.map {
case (u, pt) => {
@leaderboard.map { l =>
<tr>
<td>@userLink(u)</td>
<td>@showPerfRating(u, pt, klass = "title")</td>
<td>@showProgress(u.perfs(pt).progress, withTitle = false)</td>
<td>@lightUserLink(l.user)</td>
@lila.rating.PerfType(l.perfKey).map { pt =>
<td data-icon="@pt.iconChar">l.rating</td>
}
<td>@showProgress(l.progress, withTitle = false)</td>
</tr>
}
}
</tbody>
</table>
</div>

View File

@ -1,20 +1,18 @@
@(tourneyWinners: List[lila.tournament.Winner], online: List[User], bullet: List[User], blitz: List[User], classical: List[User], chess960: List[User], kingOfTheHill: List[User], threeCheck: List[User], antichess: List[User], atomic: List[User], horde: List[User], nbDay: List[(User, Int)], nbAllTime: List[(User, Int)])(implicit ctx: Context)
@(tourneyWinners: List[lila.tournament.Winner], online: List[User], bullet: List[User.LightPerf], blitz: List[User.LightPerf], classical: List[User.LightPerf], chess960: List[User.LightPerf], kingOfTheHill: List[User.LightPerf], threeCheck: List[User.LightPerf], antichess: List[User.LightPerf], atomic: List[User.LightPerf], horde: List[User.LightPerf], nbDay: List[User.LightCount], nbAllTime: List[User.LightCount])(implicit ctx: Context)
@import lila.rating.PerfType
@userTopPerf(users: List[User], perfType: PerfType) = {
@userTopPerf(users: List[User.LightPerf], perfType: PerfType) = {
<div class="user_top">
<h2 class="text" data-icon="@perfType.iconChar">
<a href="@routes.User.top200(perfType.key)">
@perfType.name
</a>
<a href="@routes.User.top200(perfType.key)">@perfType.name</a>
</h2>
<table>
<tbody>
@users.map { u =>
@users.map { l =>
<tr>
<td>@userLink(u)</td>
<td>@u.perfs(perfType.key).map(_.intRating)</td>
<td>@lightUserLink(l.user)</td>
<td>@l.rating</td>
</tr>
}
</tbody>
@ -22,15 +20,15 @@
</div>
}
@userTopActive(users: List[(User, Int)], title: Any, icon: Option[Char] = None) = {
@userTopActive(users: List[User.LightCount], title: Any, icon: Option[Char] = None) = {
<div class="user_top">
<h2 class="text"@icon.map { i => data-icon="@i" }>@title</h2>
<table>
<tbody>
@users.map { u =>
<tr>
<td>@userLink(u._1)</td>
<td title="@trans.gamesPlayed()">#@u._2.localize</td>
<td>@lightUserLink(u.user)</td>
<td title="@trans.gamesPlayed()">#@u.count.localize</td>
</tr>
}
</tbody>

View File

@ -12,8 +12,8 @@ import lila.db.BSON._
import lila.db.Implicits._
import lila.memo.{ ExpireSetMemo, MongoCache }
import lila.rating.{ Perf, PerfType }
import User.LightPerf
import tube.userTube
import User.{ LightPerf, LightCount }
final class Cached(
nbTtl: FiniteDuration,
@ -30,13 +30,15 @@ final class Cached(
def countEnabled: Fu[Int] = countCache(true)
private implicit val userHandler = User.userBSONHandler
private implicit val LightUserBSONHandler = reactivemongo.bson.Macros.handler[LightUser]
private implicit val LightPerfBSONHandler = reactivemongo.bson.Macros.handler[LightPerf]
private implicit val LightCountBSONHandler = reactivemongo.bson.Macros.handler[LightCount]
val top10Perf = mongoCache[Perf.Key, List[User]](
val top10Perf = mongoCache[Perf.Key, List[LightPerf]](
prefix = "user:top10:perf",
f = (perf: Perf.Key) => UserRepo.topPerfSince(perf, oneWeekAgo, 10),
f = (perf: Perf.Key) => UserRepo.topPerfSince(perf, oneWeekAgo, 10) map {
_ flatMap (_ lightPerf perf)
},
timeToLive = 10 minutes)
val top200Perf = mongoCache[Perf.Key, List[User.LightPerf]](
@ -46,26 +48,20 @@ final class Cached(
},
timeToLive = 10 minutes)
private case class UserPerf(user: User, perfKey: String)
private implicit val UserPerfBSONHandler = reactivemongo.bson.Macros.handler[UserPerf]
private val topTodayCache = mongoCache.single[List[UserPerf]](
private val topTodayCache = mongoCache.single[List[User.LightPerf]](
prefix = "user:top:today",
f = PerfType.leaderboardable.map { perf =>
UserRepo.topPerfSince(perf.key, DateTime.now minusHours 12, 1) map2 { (u: User) =>
UserPerf(u, perf.key)
UserRepo.topPerfSince(perf.key, DateTime.now minusHours 12, 1).map {
_.headOption flatMap (_ lightPerf perf.key)
}
}.sequenceFu map (_.flatten),
}.sequenceFu.map(_.flatten),
timeToLive = 9 minutes)
def topToday(x: Boolean): Fu[List[(User, PerfType)]] =
topTodayCache(x) map2 { (up: UserPerf) =>
(up.user, PerfType(up.perfKey) err s"No such perf ${up.perfKey}")
}
def topToday = topTodayCache.apply _
val topNbGame = mongoCache[Int, List[User]](
val topNbGame = mongoCache[Int, List[User.LightCount]](
prefix = "user:top:nbGame",
f = UserRepo.topNbGame,
f = nb => UserRepo topNbGame nb map { _ map (_.lightCount) },
timeToLive = 34 minutes)
val topOnline = lila.memo.AsyncCache[Int, List[User]](

View File

@ -72,8 +72,10 @@ case class User(
def lameOrTroll = lame || troll
def lightPerf(key: String) = perfs(key) map { perf =>
User.LightPerf(light, perf.intRating, perf.progress)
User.LightPerf(light, key, perf.intRating, perf.progress)
}
def lightCount = User.LightCount(light, count.game)
}
object User {
@ -82,10 +84,8 @@ object User {
val anonymous = "Anonymous"
case class LightPerf(
user: LightUser,
rating: Int,
progress: Int)
case class LightPerf(user: LightUser, perfKey: String, rating: Int, progress: Int)
case class LightCount(user: LightUser, count: Int)
case class Active(user: User)