collect all pairings users in one request

This commit is contained in:
Thibault Duplessis 2017-04-03 01:35:11 +02:00
parent c427bc774e
commit deade5fa0f
6 changed files with 31 additions and 38 deletions

View file

@ -64,6 +64,11 @@ trait CollExt { self: dsl with QueryBuilderExt =>
ids.map(docsMap.get)(breakOut)
}
def idsMap[D: BSONDocumentReader, I: BSONValueWriter](ids: Iterable[I], readPreference: ReadPreference = ReadPreference.primary)(docId: D => I): Fu[Map[I, D]] =
byIds[D, I](ids, readPreference) map { docs =>
docs.map(u => docId(u) -> u)(breakOut)
}
def primitive[V: BSONValueReader](selector: Bdoc, field: String): Fu[List[V]] =
coll.find(selector, $doc(field -> true))
.list[Bdoc]()

View file

@ -411,19 +411,6 @@ object GameRepo {
.skip(Random nextInt 1000)
.uno[Game]
def findMirror(game: Game): Fu[Option[Game]] = coll.uno[Game]($doc(
F.id -> $doc("$ne" -> game.id),
F.playerUids $in game.userIds,
F.status -> Status.Started.id,
F.createdAt $gt (DateTime.now minusMinutes 15),
F.updatedAt $gt (DateTime.now minusMinutes 5),
"$or" -> $arr(
$doc(s"${F.whitePlayer}.ai" -> $doc("$exists" -> true)),
$doc(s"${F.blackPlayer}.ai" -> $doc("$exists" -> true))
),
F.binaryPieces -> game.binaryPieces
))
def hydrateUpdatedAtAndTvAt(game: Game): Fu[Game] =
coll.find($id(game.id), $doc(F.updatedAt -> true, F.tvAt -> true)).uno[Bdoc].map {
_.fold(game) { o =>

View file

@ -25,10 +25,10 @@ final class AutoPairing(
onStart: String => Unit
) {
def apply(tour: Tournament, pairing: Pairing): Fu[Game] = for {
user1 getUser(pairing.user1)
user2 getUser(pairing.user2)
game1 = Game.make(
def apply(tour: Tournament, pairing: Pairing, usersMap: Map[User.ID, User]): Fu[Game] = {
val user1 = usersMap get pairing.user1 err s"Missing pairing user $pairing"
val user2 = usersMap get pairing.user2 err s"Missing pairing user $pairing"
val game1 = Game.make(
game = chess.Game(
variantOption = tour.variant.some,
fen = tour.position.some.filterNot(_.initial).map(_.fen)
@ -49,21 +49,17 @@ final class AutoPairing(
source = Source.Tournament,
pgnImport = None
)
game2 = game1
val game2 = game1
.updatePlayer(Color.White, _.withUser(user1.id, PerfPicker.mainOrDefault(game1)(user1.perfs)))
.updatePlayer(Color.Black, _.withUser(user2.id, PerfPicker.mainOrDefault(game1)(user2.perfs)))
.withTournamentId(tour.id)
.withId(pairing.gameId)
.start
_ (GameRepo insertDenormalized game2) >>-
(GameRepo insertDenormalized game2) >>-
scheduleIdleCheck(PovRef(game2.id, game2.turnColor), SecondsToDoFirstMove.secondsToMoveFor(tour), true) >>-
onStart(game2.id)
} yield game2
private def getUser(username: String): Fu[User] =
UserRepo named username flatMap {
_.fold(fufail[User]("No user named " + username))(fuccess)
}
onStart(game2.id) inject
game2
}
private def scheduleIdleCheck(povRef: PovRef, secondsToMove: Int, thenAgain: Boolean) {
system.scheduler.scheduleOnce(secondsToMove seconds)(idleCheck(povRef, secondsToMove, thenAgain))

View file

@ -97,10 +97,10 @@ object PlayerRepo {
selectTour(tourId) ++ $doc("m" -> $doc("$gt" -> 0))
).cursor[Player]().gather[List]()
def userIds(tourId: String): Fu[List[String]] =
private[tournament] def userIds(tourId: String): Fu[List[String]] =
coll.distinct[String, List]("uid", selectTour(tourId).some)
def activeUserIds(tourId: String): Fu[List[String]] =
private[tournament] def activeUserIds(tourId: String): Fu[List[String]] =
coll.distinct[String, List](
"uid", (selectTour(tourId) ++ selectActive).some
)

View file

@ -72,13 +72,15 @@ final class TournamentApi(
pairingLogger.warn(s"Give up making https://lichess.org/tournament/${tour.id} ${pairings.size} pairings in ${nowMillis - startAt}ms")
lila.mon.tournament.pairing.giveup()
funit
case pairings => pairings.map { pairing =>
PairingRepo.insert(pairing) >>
autoPairing(tour, pairing) addEffect { game =>
sendTo(tour.id, StartGame(game))
}
}.sequenceFu >> featureOneOf(tour, pairings, ranking) >>- {
lila.mon.tournament.pairing.create(pairings.size)
case pairings => UserRepo.idsMap(pairings.flatMap(_.users)) flatMap { users =>
pairings.map { pairing =>
PairingRepo.insert(pairing) >>
autoPairing(tour, pairing, users) addEffect { game =>
sendTo(tour.id, StartGame(game))
}
}.sequenceFu >> featureOneOf(tour, pairings, ranking) >>- {
lila.mon.tournament.pairing.create(pairings.size)
}
}
} >>- {
val time = nowMillis - startAt

View file

@ -49,6 +49,12 @@ object UserRepo {
def byOrderedIds(ids: Seq[ID], readPreference: ReadPreference): Fu[List[User]] =
coll.byOrderedIds[User, User.ID](ids, readPreference)(_.id)
def idsMap(ids: Seq[ID], readPreference: ReadPreference = ReadPreference.secondaryPreferred): Fu[Map[User.ID, User]] =
coll.idsMap[User, User.ID](ids, readPreference)(_.id)
def usersFromSecondary(userIds: Seq[ID]): Fu[List[User]] =
byOrderedIds(userIds, ReadPreference.secondaryPreferred)
def enabledByIds(ids: Iterable[ID]): Fu[List[User]] =
coll.list[User](enabledSelect ++ $inIds(ids), ReadPreference.secondaryPreferred)
@ -78,9 +84,6 @@ object UserRepo {
_.flatMap { _.getAs[String]("_id") }
}
def usersFromSecondary(userIds: Seq[ID]): Fu[List[User]] =
byOrderedIds(userIds, ReadPreference.secondaryPreferred)
private[user] def allSortToints(nb: Int) =
coll.find($empty).sort($sort desc F.toints).cursor[User]().gather[List](nb)