cache more game collection queries
This commit is contained in:
parent
e1f32fa38b
commit
922571e8ec
|
@ -29,6 +29,7 @@ final class Env(
|
||||||
bookmarkApi = Env.bookmark.api,
|
bookmarkApi = Env.bookmark.api,
|
||||||
eloCalculator = Env.round.eloCalculator,
|
eloCalculator = Env.round.eloCalculator,
|
||||||
relationApi = Env.relation.api,
|
relationApi = Env.relation.api,
|
||||||
|
gameCached = Env.game.cached,
|
||||||
postApi = Env.forum.postApi,
|
postApi = Env.forum.postApi,
|
||||||
getRank = Env.user.ranking.get) _
|
getRank = Env.user.ranking.get) _
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ object Tv extends LilaController {
|
||||||
private def confrontation(game: GameModel): Fu[Option[Confrontation]] = ~{
|
private def confrontation(game: GameModel): Fu[Option[Confrontation]] = ~{
|
||||||
(game.creator.userId |@| game.invited.userId) apply {
|
(game.creator.userId |@| game.invited.userId) apply {
|
||||||
case (id1, id2) ⇒ (UserRepo byId id1) zip (UserRepo byId id2) flatMap {
|
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)
|
case _ ⇒ fuccess(none)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,16 +36,17 @@ object UserInfo {
|
||||||
bookmarkApi: BookmarkApi,
|
bookmarkApi: BookmarkApi,
|
||||||
eloCalculator: EloCalculator,
|
eloCalculator: EloCalculator,
|
||||||
relationApi: RelationApi,
|
relationApi: RelationApi,
|
||||||
|
gameCached: lila.game.Cached,
|
||||||
postApi: PostApi,
|
postApi: PostApi,
|
||||||
getRank: String ⇒ Fu[Option[Int]])(user: User, ctx: Context): Fu[UserInfo] =
|
getRank: String ⇒ Fu[Option[Int]])(user: User, ctx: Context): Fu[UserInfo] =
|
||||||
(getRank(user.id) flatMap {
|
(getRank(user.id) flatMap {
|
||||||
_ ?? { rank ⇒ countUsers() map { nb ⇒ (rank -> nb).some } }
|
_ ?? { rank ⇒ countUsers() map { nb ⇒ (rank -> nb).some } }
|
||||||
}) zip
|
}) zip
|
||||||
((ctx is user) ?? {
|
((ctx is user) ?? {
|
||||||
GameRepo count (_ notFinished user.id) map (_.some)
|
gameCached nbPlaying user.id map (_.some)
|
||||||
}) zip
|
}) zip
|
||||||
(ctx.me.filter(user!=) ?? { me ⇒
|
(ctx.me.filter(user!=) ?? { me ⇒
|
||||||
GameRepo.confrontation(me, user) map (_.some filterNot (_.empty))
|
gameCached.confrontation(me, user) map (_.some filterNot (_.empty))
|
||||||
}) zip
|
}) zip
|
||||||
(bookmarkApi countByUser user) zip
|
(bookmarkApi countByUser user) zip
|
||||||
EloChart(user) zip
|
EloChart(user) zip
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@(c: lila.user.Confrontation)(implicit ctx: Context)
|
@(c: lila.user.Confrontation)(implicit ctx: Context)
|
||||||
|
|
||||||
<div class="confrontation boxed_data">
|
<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.nbWins("<strong>"+c.wins+"</strong>"),
|
||||||
@trans.nbDraws("<strong>"+c.draws+"</strong>"),
|
@trans.nbDraws("<strong>"+c.draws+"</strong>"),
|
||||||
@trans.nbLosses("<strong>"+c.losses+"</strong>")
|
@trans.nbLosses("<strong>"+c.losses+"</strong>")
|
||||||
|
|
|
@ -9,15 +9,23 @@ import lila.memo.AsyncCache
|
||||||
import lila.user.{ User, Confrontation }
|
import lila.user.{ User, Confrontation }
|
||||||
import tube.gameTube
|
import tube.gameTube
|
||||||
|
|
||||||
private[game] final class Cached(ttl: Duration) {
|
final class Cached(ttl: Duration) {
|
||||||
|
|
||||||
def nbGames: Fu[Int] = count(Query.all)
|
def nbGames: Fu[Int] = count(Query.all)
|
||||||
def nbMates: Fu[Int] = count(Query.mate)
|
def nbMates: Fu[Int] = count(Query.mate)
|
||||||
def nbPopular: Fu[Int] = count(Query.popular)
|
def nbPopular: Fu[Int] = count(Query.popular)
|
||||||
def nbImported: Fu[Int] = count(Query.imported)
|
def nbImported: Fu[Int] = count(Query.imported)
|
||||||
|
|
||||||
def confrontation(user1: User, user2: User): Fu[Confrontation] =
|
def nbPlaying(userId: String): Fu[Int] = count(Query notFinished userId)
|
||||||
confrontationCache(List(user1, user2).sortBy(_.count.game).map(_.id))
|
|
||||||
|
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 =
|
private val confrontationCache =
|
||||||
AsyncCache(GameRepo.confrontation, timeToLive = 1.minute)
|
AsyncCache(GameRepo.confrontation, timeToLive = 1.minute)
|
||||||
|
|
|
@ -226,32 +226,37 @@ object GameRepo {
|
||||||
_ sort Query.sortCreated skip (Random nextInt 1000)
|
_ 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
|
// the 2 userIds SHOULD be sorted by game count desc
|
||||||
// this method is cached in lila.game.Cached
|
// this method is cached in lila.game.Cached
|
||||||
private[game] def confrontation(userIds: List[String]): Fu[Confrontation] = {
|
private[game] def confrontation(users: ((String, Int), (String, Int))): Fu[Confrontation] = users match {
|
||||||
import reactivemongo.bson._
|
case (user1, user2) ⇒ {
|
||||||
import reactivemongo.core.commands._
|
import reactivemongo.bson._
|
||||||
val command = Aggregate(gameTube.coll.name, Seq(
|
import reactivemongo.core.commands._
|
||||||
Match(BSONDocument(
|
val userIds = List(user1, user2).sortBy(_._2).map(_._1)
|
||||||
"uids" -> BSONDocument("$all" -> userIds),
|
val command = Aggregate(gameTube.coll.name, Seq(
|
||||||
"s" -> BSONDocument("$gte" -> chess.Status.Mate.id)
|
Match(BSONDocument(
|
||||||
)),
|
"uids" -> BSONDocument("$all" -> userIds),
|
||||||
GroupField("wid")("nb" -> SumValue(1))
|
"s" -> BSONDocument("$gte" -> chess.Status.Mate.id)
|
||||||
))
|
)),
|
||||||
gameTube.coll.db.command(command) map { stream ⇒
|
GroupField("wid")("nb" -> SumValue(1))
|
||||||
val res = (stream.toList map { obj ⇒
|
))
|
||||||
toJSON(obj).asOpt[JsObject] flatMap { o ⇒
|
gameTube.coll.db.command(command) map { stream ⇒
|
||||||
o int "nb" map { nb ⇒
|
val res = (stream.toList map { obj ⇒
|
||||||
~(o str "_id") -> nb
|
toJSON(obj).asOpt[JsObject] flatMap { o ⇒
|
||||||
|
o int "nb" map { nb ⇒
|
||||||
|
~(o str "_id") -> nb
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}).flatten.toMap
|
||||||
}).flatten.toMap
|
Confrontation(
|
||||||
Confrontation(
|
user1._1, user2._1,
|
||||||
~(res get ~userIds.lift(0)),
|
~(res get user1._1),
|
||||||
~(res get ""),
|
~(res get ""),
|
||||||
~(res get ~userIds.lift(1))
|
~(res get user2._1)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package lila.user
|
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
|
def games = wins + draws + losses
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue