cache more game collection queries

pull/83/head
Thibault Duplessis 2013-09-18 02:40:25 +02:00
parent e1f32fa38b
commit 922571e8ec
7 changed files with 51 additions and 31 deletions

View File

@ -29,6 +29,7 @@ final class Env(
bookmarkApi = Env.bookmark.api,
eloCalculator = Env.round.eloCalculator,
relationApi = Env.relation.api,
gameCached = Env.game.cached,
postApi = Env.forum.postApi,
getRank = Env.user.ranking.get) _

View File

@ -36,7 +36,7 @@ object Tv extends LilaController {
private def confrontation(game: GameModel): Fu[Option[Confrontation]] = ~{
(game.creator.userId |@| game.invited.userId) apply {
case (id1, id2) (UserRepo byId id1) zip (UserRepo byId id2) flatMap {
case (Some(user1), Some(user2)) GameRepo.confrontation(user1, user2) map (_.some)
case (Some(user1), Some(user2)) Env.game.cached.confrontation(user1, user2) map (_.some)
case _ fuccess(none)
}
}

View File

@ -36,16 +36,17 @@ object UserInfo {
bookmarkApi: BookmarkApi,
eloCalculator: EloCalculator,
relationApi: RelationApi,
gameCached: lila.game.Cached,
postApi: PostApi,
getRank: String Fu[Option[Int]])(user: User, ctx: Context): Fu[UserInfo] =
(getRank(user.id) flatMap {
_ ?? { rank countUsers() map { nb (rank -> nb).some } }
}) zip
((ctx is user) ?? {
GameRepo count (_ notFinished user.id) map (_.some)
gameCached nbPlaying user.id map (_.some)
}) zip
(ctx.me.filter(user!=) ?? { me
GameRepo.confrontation(me, user) map (_.some filterNot (_.empty))
gameCached.confrontation(me, user) map (_.some filterNot (_.empty))
}) zip
(bookmarkApi countByUser user) zip
EloChart(user) zip

View File

@ -1,7 +1,7 @@
@(c: lila.user.Confrontation)(implicit ctx: Context)
<div class="confrontation boxed_data">
<div class="vs">@userLink(c.user1, withElo = false, withOnline = false) vs @userLink(c.user2, withElo = false, withOnline = false)</div>
<div class="vs">@userIdLink(c.user1.some, withOnline = false) vs @userIdLink(c.user2.some, withOnline = false)</div>
@trans.nbWins("<strong>"+c.wins+"</strong>"),
@trans.nbDraws("<strong>"+c.draws+"</strong>"),
@trans.nbLosses("<strong>"+c.losses+"</strong>")

View File

@ -9,15 +9,23 @@ import lila.memo.AsyncCache
import lila.user.{ User, Confrontation }
import tube.gameTube
private[game] final class Cached(ttl: Duration) {
final class Cached(ttl: Duration) {
def nbGames: Fu[Int] = count(Query.all)
def nbMates: Fu[Int] = count(Query.mate)
def nbPopular: Fu[Int] = count(Query.popular)
def nbImported: Fu[Int] = count(Query.imported)
def confrontation(user1: User, user2: User): Fu[Confrontation] =
confrontationCache(List(user1, user2).sortBy(_.count.game).map(_.id))
def nbPlaying(userId: String): Fu[Int] = count(Query notFinished userId)
def confrontation(user1: User, user2: User): Fu[Confrontation] = {
def idGame(user: User) = (user.id, user.count.game)
confrontationCache {
(user1 < user2).fold(
idGame(user1) -> idGame(user2),
idGame(user2) -> idGame(user1))
}
}
private val confrontationCache =
AsyncCache(GameRepo.confrontation, timeToLive = 1.minute)

View File

@ -226,32 +226,37 @@ object GameRepo {
_ sort Query.sortCreated skip (Random nextInt 1000)
)
// user1 wins, draws, losses
// gets 2 users (id, nbGames)
// returns user1 wins, draws, losses
// the 2 userIds SHOULD be sorted by game count desc
// this method is cached in lila.game.Cached
private[game] def confrontation(userIds: List[String]): Fu[Confrontation] = {
import reactivemongo.bson._
import reactivemongo.core.commands._
val command = Aggregate(gameTube.coll.name, Seq(
Match(BSONDocument(
"uids" -> BSONDocument("$all" -> userIds),
"s" -> BSONDocument("$gte" -> chess.Status.Mate.id)
)),
GroupField("wid")("nb" -> SumValue(1))
))
gameTube.coll.db.command(command) map { stream
val res = (stream.toList map { obj
toJSON(obj).asOpt[JsObject] flatMap { o
o int "nb" map { nb
~(o str "_id") -> nb
private[game] def confrontation(users: ((String, Int), (String, Int))): Fu[Confrontation] = users match {
case (user1, user2) {
import reactivemongo.bson._
import reactivemongo.core.commands._
val userIds = List(user1, user2).sortBy(_._2).map(_._1)
val command = Aggregate(gameTube.coll.name, Seq(
Match(BSONDocument(
"uids" -> BSONDocument("$all" -> userIds),
"s" -> BSONDocument("$gte" -> chess.Status.Mate.id)
)),
GroupField("wid")("nb" -> SumValue(1))
))
gameTube.coll.db.command(command) map { stream
val res = (stream.toList map { obj
toJSON(obj).asOpt[JsObject] flatMap { o
o int "nb" map { nb
~(o str "_id") -> nb
}
}
}
}).flatten.toMap
Confrontation(
~(res get ~userIds.lift(0)),
~(res get ""),
~(res get ~userIds.lift(1))
)
}).flatten.toMap
Confrontation(
user1._1, user2._1,
~(res get user1._1),
~(res get ""),
~(res get user2._1)
)
}
}
}
}

View File

@ -1,6 +1,11 @@
package lila.user
case class Confrontation(wins: Int, draws: Int, losses: Int) {
case class Confrontation(
user1: String,
user2: String,
wins: Int,
draws: Int,
losses: Int) {
def games = wins + draws + losses