cache more game collection queries
parent
e1f32fa38b
commit
922571e8ec
|
@ -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) _
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue