refactor and monitor an expensive db aggregation

pull/9131/head
Thibault Duplessis 2021-06-07 10:12:18 +02:00
parent 13d6bd8f36
commit 6b9a3673c8
4 changed files with 32 additions and 48 deletions

View File

@ -396,6 +396,7 @@ object mon {
"client" -> client
)
)
def withdrawableIds(reason: String) = future("tournament.withdrawableIds", reason)
}
object swiss {
def standingOverload = counter("swiss.standing.overload").withoutTags()

View File

@ -54,7 +54,7 @@ final private[tournament] class ApiActor(
}
private def ejectFromEnterable(userId: User.ID) =
tournamentRepo.withdrawableIds(userId) flatMap {
tournamentRepo.withdrawableIds(userId, reason = "ejectFromEnterable") flatMap {
_.map {
api.ejectLameFromEnterable(_, userId)
}.sequenceFu

View File

@ -380,7 +380,7 @@ final class TournamentApi(
}
def withdrawAll(user: User): Funit =
tournamentRepo.withdrawableIds(user.id) flatMap {
tournamentRepo.withdrawableIds(user.id, reason = "withdrawAll") flatMap {
_.map {
withdraw(_, user.id, isPause = false, isStalling = false)
}.sequenceFu.void
@ -467,14 +467,14 @@ final class TournamentApi(
} withdraw(tourId, userId, isPause = false, isStalling = false)
def pausePlaybanned(userId: User.ID) =
tournamentRepo.withdrawableIds(userId) flatMap {
tournamentRepo.withdrawableIds(userId, reason = "pausePlaybanned") flatMap {
_.map {
playerRepo.withdraw(_, userId)
}.sequenceFu.void
}
private[tournament] def kickFromTeam(teamId: TeamID, userId: User.ID): Funit =
tournamentRepo.withdrawableIds(userId, teamId = teamId.some) flatMap {
tournamentRepo.withdrawableIds(userId, teamId = teamId.some, reason = "kickFromTeam") flatMap {
_.map { tourId =>
Sequencing(tourId)(tournamentRepo.byId) { tour =>
val fu =

View File

@ -102,33 +102,34 @@ final class TournamentRepo(val coll: Coll, playerCollName: CollName)(implicit
readPreference = ReadPreference.secondaryPreferred
)
private def lookupPlayer(userId: User.ID, project: Option[Bdoc]) =
$doc(
"$lookup" -> $doc(
"from" -> playerCollName.value,
"let" -> $doc("tid" -> "$_id"),
"pipeline" -> $arr(
$doc(
"$match" -> $doc(
"$expr" -> $doc(
"$and" -> $arr(
$doc("$eq" -> $arr("$uid", userId)),
$doc("$eq" -> $arr("$tid", "$$tid"))
)
)
)
),
project.map { p => $doc(s"$$project" -> p) }
),
"as" -> "player"
)
)
private[tournament] def upcomingAdapterExpensiveCacheMe(userId: User.ID, max: Int) =
coll
.aggregateList(max, readPreference = ReadPreference.secondaryPreferred) { implicit framework =>
import framework._
Match(enterableSelect ++ nonEmptySelect) -> List(
PipelineOperator(
$doc(
"$lookup" -> $doc(
"from" -> playerCollName.value,
"let" -> $doc("tid" -> "$_id"),
"pipeline" -> $arr(
$doc(
"$match" -> $doc(
"$expr" -> $doc(
"$and" -> $arr(
$doc("$eq" -> $arr("$uid", userId)),
$doc("$eq" -> $arr("$tid", "$$tid"))
)
)
)
),
$doc("$project" -> $doc("tid" -> true, "_id" -> false))
),
"as" -> "player"
)
)
),
PipelineOperator(lookupPlayer(userId, $doc("tid" -> true, "_id" -> false).some)),
Match("player" $ne $arr()),
Sort(Ascending("startsAt")),
Limit(max)
@ -184,38 +185,20 @@ final class TournamentRepo(val coll: Coll, playerCollName: CollName)(implicit
private[tournament] def withdrawableIds(
userId: User.ID,
teamId: Option[TeamID] = None
teamId: Option[TeamID] = None,
reason: String
): Fu[List[Tournament.ID]] =
coll
.aggregateList(Int.MaxValue, readPreference = ReadPreference.secondaryPreferred) { implicit framework =>
import framework._
Match(enterableSelect ++ nonEmptySelect ++ teamId.??(forTeamSelect)) -> List(
PipelineOperator(
$doc(
"$lookup" -> $doc(
"from" -> playerCollName.value,
"let" -> $doc("t" -> "$_id"),
"pipeline" -> $arr(
$doc(
"$match" -> $doc(
"$expr" -> $doc(
"$and" -> $arr(
$doc("$eq" -> $arr("$uid", userId)),
$doc("$eq" -> $arr("$tid", "$$t"))
)
)
)
)
),
"as" -> "player"
)
)
),
PipelineOperator(lookupPlayer(userId, none)),
Match("player" $ne $arr()),
Project($id(true))
)
}
.map(_.flatMap(_.string("_id")))
.monSuccess(_.tournament.withdrawableIds(reason))
def setStatus(tourId: Tournament.ID, status: Status) =
coll.updateField($id(tourId), "status", status.id).void