remove game2.turns & game2.updatedAt indexes, cache more counts
This commit is contained in:
parent
4a86d2c27d
commit
2ee23eca20
|
@ -36,10 +36,4 @@ object Monitor extends LilaController {
|
|||
(reporting ? GetNbMembers).mapTo[Int].asPromise map { Ok(_) }
|
||||
}
|
||||
}
|
||||
|
||||
val nbPlaying = Action {
|
||||
Async {
|
||||
(reporting ? GetNbPlaying).mapTo[Int].asPromise map { Ok(_) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ final class Titivate(
|
|||
val cleanupNext: IO[Unit] = {
|
||||
|
||||
val cursor = gameRepo.collection.find(
|
||||
("next" $exists true) ++ ("updatedAt" $gt (DateTime.now - 3.days)),
|
||||
("next" $exists true) ++ ("createdAt" $gt (DateTime.now - 3.days)),
|
||||
DBObject("next" -> true)
|
||||
)
|
||||
val unsetNext = (id: String) ⇒ gameRepo.collection.update(
|
||||
|
|
|
@ -19,6 +19,7 @@ final class GameEnv(
|
|||
|
||||
lazy val paginator = new PaginatorBuilder(
|
||||
gameRepo = gameRepo,
|
||||
cached = cached,
|
||||
maxPerPage = GamePaginatorMaxPerPage)
|
||||
|
||||
lazy val export = Export(gameRepo) _
|
||||
|
|
|
@ -55,7 +55,7 @@ class GameRepo(collection: MongoCollection)
|
|||
def save(progress: Progress): IO[Unit] =
|
||||
new GameDiff(progress.origin.encode, progress.game.encode)() |> { diffs ⇒
|
||||
if (diffs.nonEmpty) {
|
||||
val fullDiffs = ("updatedAt" -> new Date()) :: diffs
|
||||
val fullDiffs = ("updatedAt" -> new Date) :: diffs
|
||||
io { update(idSelector(progress.origin), $set(fullDiffs: _*)) }
|
||||
}
|
||||
else io()
|
||||
|
@ -131,7 +131,7 @@ class GameRepo(collection: MongoCollection)
|
|||
primitiveProjection[String](idSelector(gameId), "initialFen")
|
||||
}
|
||||
|
||||
def unplayedIds: IO[List[String]] = io {
|
||||
val unplayedIds: IO[List[String]] = io {
|
||||
primitiveProjections[String](
|
||||
("turns" $lt 2) ++ ("createdAt" $lt (DateTime.now - 2.day)),
|
||||
"_id"
|
||||
|
@ -150,6 +150,7 @@ class GameRepo(collection: MongoCollection)
|
|||
def candidatesToAutofinish: IO[List[DbGame]] = io {
|
||||
find(Query.playable ++
|
||||
Query.clock(true) ++
|
||||
("createdAt" $gt (DateTime.now - 1.day)) ++ // index
|
||||
("updatedAt" $lt (DateTime.now - 2.hour))
|
||||
).toList.map(_.decode).flatten
|
||||
}
|
||||
|
@ -163,8 +164,8 @@ class GameRepo(collection: MongoCollection)
|
|||
def exists(id: String) = count(idSelector(id)) map (_ > 0)
|
||||
|
||||
def recentGames(limit: Int): IO[List[DbGame]] = io {
|
||||
find(Query.started)
|
||||
.sort(DBObject("updatedAt" -> -1))
|
||||
find(Query.started ++ Query.turnsGt(1))
|
||||
.sort(DBObject("createdAt" -> -1))
|
||||
.limit(limit)
|
||||
.toList.map(_.decode).flatten sortBy (_.id)
|
||||
}
|
||||
|
|
|
@ -3,43 +3,53 @@ package game
|
|||
|
||||
import user.User
|
||||
import chess.Status
|
||||
import mongodb.CachedAdapter
|
||||
|
||||
import com.github.ornicar.paginator._
|
||||
import com.mongodb.casbah.Imports._
|
||||
|
||||
final class PaginatorBuilder(
|
||||
gameRepo: GameRepo,
|
||||
cached: Cached,
|
||||
maxPerPage: Int) {
|
||||
|
||||
def recent(page: Int): Paginator[DbGame] =
|
||||
def recent(page: Int): Paginator[DbGame] =
|
||||
paginator(recentAdapter, page)
|
||||
|
||||
def checkmate(page: Int): Paginator[DbGame] =
|
||||
def checkmate(page: Int): Paginator[DbGame] =
|
||||
paginator(checkmateAdapter, page)
|
||||
|
||||
def popular(page: Int): Paginator[DbGame] =
|
||||
def popular(page: Int): Paginator[DbGame] =
|
||||
paginator(popularAdapter, page)
|
||||
|
||||
def recentlyUpdated(query: DBObject) = apply(query, Query.sortUpdated) _
|
||||
|
||||
def recentlyCreated(query: DBObject) = apply(query, Query.sortCreated) _
|
||||
|
||||
def apply(query: DBObject, sort: DBObject)(page: Int): Paginator[DbGame] =
|
||||
apply(adapter(query, sort))(page)
|
||||
def apply(query: DBObject, sort: DBObject)(page: Int): Paginator[DbGame] =
|
||||
apply(noCacheAdapter(query, sort))(page)
|
||||
|
||||
private def apply(adapter: Adapter[DbGame])(page: Int): Paginator[DbGame] =
|
||||
paginator(adapter, page)
|
||||
|
||||
private val recentAdapter =
|
||||
adapter(DBObject(), Query.sortUpdated)
|
||||
private val recentAdapter =
|
||||
adapter(DBObject(), Query.sortCreated, cached.nbGames)
|
||||
|
||||
private val checkmateAdapter =
|
||||
adapter(Query.mate, Query.sortUpdated)
|
||||
private val checkmateAdapter =
|
||||
adapter(Query.mate, Query.sortCreated, cached.nbMates)
|
||||
|
||||
private val popularAdapter =
|
||||
adapter(Query.popular, Query.sortPopular)
|
||||
private val popularAdapter =
|
||||
adapter(Query.popular, Query.sortPopular, cached.nbPopular)
|
||||
|
||||
private def adapter(query: DBObject, sort: DBObject) = SalatAdapter(
|
||||
private def adapter(
|
||||
query: DBObject,
|
||||
sort: DBObject,
|
||||
nbResults: Int) = new CachedAdapter(
|
||||
dao = gameRepo,
|
||||
query = query,
|
||||
sort = sort,
|
||||
nbResults = nbResults
|
||||
) map (_.decode.get) // unsafe
|
||||
|
||||
private def noCacheAdapter(query: DBObject, sort: DBObject) = SalatAdapter(
|
||||
dao = gameRepo,
|
||||
query = query,
|
||||
sort = sort
|
||||
|
|
|
@ -21,8 +21,6 @@ object Query {
|
|||
|
||||
val playable: DBObject = ("status" $lt Status.Aborted.id)
|
||||
|
||||
val playing: DBObject = "updatedAt" $gt (DateTime.now - 15.seconds)
|
||||
|
||||
val mate: DBObject = DBObject("status" -> Status.Mate.id)
|
||||
|
||||
val draw: DBObject = "status" $in List(Status.Draw.id, Status.Stalemate.id)
|
||||
|
@ -51,9 +49,9 @@ object Query {
|
|||
|
||||
def opponents(u1: User, u2: User) = "userIds" $all List(u1.id, u2.id)
|
||||
|
||||
val sortCreated = DBObject("createdAt" -> -1)
|
||||
def turnsGt(nb: Int) = "turns" $gt nb
|
||||
|
||||
val sortUpdated = DBObject("updatedAt" -> -1)
|
||||
val sortCreated = DBObject("createdAt" -> -1)
|
||||
|
||||
val sortPopular = DBObject("bm" -> -1)
|
||||
}
|
||||
|
|
21
app/mongodb/CachedAdapter.scala
Normal file
21
app/mongodb/CachedAdapter.scala
Normal file
|
@ -0,0 +1,21 @@
|
|||
package lila
|
||||
package mongodb
|
||||
|
||||
import com.github.ornicar.paginator._
|
||||
import com.novus.salat.dao.DAO
|
||||
import com.novus.salat._
|
||||
import com.mongodb.casbah.Imports.DBObject
|
||||
|
||||
final class CachedAdapter[A <: CaseClass, B <: Any](
|
||||
dao: DAO[A, B],
|
||||
query: DBObject,
|
||||
sort: DBObject,
|
||||
val nbResults: Int) extends Adapter[A] {
|
||||
|
||||
private val salatAdapter = SalatAdapter(
|
||||
dao = dao,
|
||||
query = query,
|
||||
sort = sort)
|
||||
|
||||
def slice(offset: Int, length: Int) = salatAdapter.slice(offset, length)
|
||||
}
|
|
@ -55,8 +55,6 @@ final class Reporting(
|
|||
|
||||
case GetNbGames ⇒ sender ! nbGames
|
||||
|
||||
case GetNbPlaying ⇒ sender ! nbPlaying
|
||||
|
||||
case GetStatus ⇒ sender ! status
|
||||
|
||||
case GetMonitorData ⇒ sender ! monitorData
|
||||
|
@ -104,7 +102,6 @@ final class Reporting(
|
|||
"lobby" -> lobby.nbMembers,
|
||||
"game" -> game.nbMembers,
|
||||
"hubs" -> game.nbHubs,
|
||||
"recent" -> nbPlaying,
|
||||
"lat." -> latency,
|
||||
"thread" -> nbThreads,
|
||||
"load" -> loadAvg.toString.replace("0.", "."),
|
||||
|
@ -122,7 +119,6 @@ final class Reporting(
|
|||
private def status = List(
|
||||
allMembers,
|
||||
nbGames,
|
||||
nbPlaying,
|
||||
game.nbHubs,
|
||||
loadAvg.toString,
|
||||
(remoteAi | 9999)
|
||||
|
|
|
@ -5,7 +5,6 @@ import core.CoreEnv
|
|||
import socket.SocketMember
|
||||
|
||||
case object GetNbGames
|
||||
case object GetNbPlaying
|
||||
case object GetStatus
|
||||
case object GetMonitorData
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ package user
|
|||
import com.github.ornicar.paginator._
|
||||
import com.mongodb.casbah.Imports.DBObject
|
||||
|
||||
import mongodb.CachedAdapter
|
||||
|
||||
final class PaginatorBuilder(
|
||||
userRepo: UserRepo,
|
||||
countUsers: () ⇒ Int,
|
||||
|
@ -15,11 +17,11 @@ final class PaginatorBuilder(
|
|||
private val recentAdapter =
|
||||
adapter(DBObject("enabled" -> true))
|
||||
|
||||
private def adapter(query: DBObject) = new Adapter[User] {
|
||||
private val salatAdapter = SalatAdapter(userRepo, query, DBObject("elo" -> -1))
|
||||
def nbResults = countUsers()
|
||||
def slice(offset: Int, length: Int) = salatAdapter.slice(offset, length)
|
||||
}
|
||||
private def adapter(query: DBObject) = new CachedAdapter(
|
||||
dao = userRepo,
|
||||
query = query,
|
||||
sort = DBObject("elo" -> -1),
|
||||
nbResults = countUsers())
|
||||
|
||||
private def paginator(adapter: Adapter[User], page: Int) = Paginator(
|
||||
adapter,
|
||||
|
|
|
@ -30,6 +30,8 @@ case class UserInfo(
|
|||
|
||||
object UserInfo {
|
||||
|
||||
private val rankMinElo = 1600
|
||||
|
||||
def apply(
|
||||
userRepo: UserRepo,
|
||||
countUsers: () => Int,
|
||||
|
@ -40,7 +42,7 @@ object UserInfo {
|
|||
bookmarkApi: BookmarkApi,
|
||||
userSpy: Option[String ⇒ IO[UserSpy]],
|
||||
ctx: Context): IO[UserInfo] = for {
|
||||
rank ← (user.elo >= 1500).fold(
|
||||
rank ← (user.elo >= rankMinElo).fold(
|
||||
userRepo rank user map { rank ⇒
|
||||
Some(rank -> countUsers())
|
||||
},
|
||||
|
|
|
@ -119,7 +119,6 @@ POST /inbox/$id<[\w]{8}>/delete controllers.Message.delete(id: String)
|
|||
GET /monitor controllers.Monitor.index
|
||||
GET /monitor/socket controllers.Monitor.websocket
|
||||
GET /nb-players controllers.Monitor.nbPlayers
|
||||
GET /nb-playing controllers.Monitor.nbPlaying
|
||||
GET /status controllers.Monitor.status
|
||||
|
||||
# Assets
|
||||
|
|
Loading…
Reference in a new issue