Skip to content

Commit

Permalink
send more distinct queries to db secondaries
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Apr 30, 2020
1 parent 4380596 commit 491a0bd
Show file tree
Hide file tree
Showing 20 changed files with 83 additions and 72 deletions.
3 changes: 2 additions & 1 deletion modules/bookmark/src/main/BookmarkApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ final class BookmarkApi(
user ?? { u =>
val candidateIds = games collect { case g if g.bookmarks > 0 => g.id }
candidateIds.nonEmpty ??
coll.distinctEasy[Game.ID, Set]("g", userIdQuery(u.id) ++ $doc("g" $in candidateIds))
coll.secondaryPreferred
.distinctEasy[Game.ID, Set]("g", userIdQuery(u.id) ++ $doc("g" $in candidateIds))
}

def removeByGameId(gameId: Game.ID): Funit =
Expand Down
2 changes: 1 addition & 1 deletion modules/clas/src/main/ClasApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ final class ClasApi(
private val idsCache = cacheApi.unit[Set[User.ID]] {
_.refreshAfterWrite(601 seconds)
.buildAsyncFuture { _ =>
coll.distinctEasy[User.ID, Set]("userId", $empty)
coll.distinctEasy[User.ID, Set]("userId", $empty, ReadPreference.secondaryPreferred)
}
}

Expand Down
2 changes: 1 addition & 1 deletion modules/coach/src/main/CoachApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ final class CoachApi(
private val languagesCache = cacheApi.unit[Set[String]] {
_.refreshAfterWrite(1 hour)
.buildAsyncFuture { _ =>
coachColl.distinctEasy[String, Set]("languages", $empty)
coachColl.secondaryPreferred.distinctEasy[String, Set]("languages", $empty)
}
}
def allLanguages: Fu[Set[String]] = languagesCache.get({})
Expand Down
5 changes: 3 additions & 2 deletions modules/db/src/main/CollExt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,14 @@ trait CollExt { self: dsl with QueryBuilderExt =>

def distinctEasy[T, M[_] <: Iterable[_]](
key: String,
selector: coll.pack.Document
selector: coll.pack.Document,
readPreference: ReadPreference = ReadPreference.primary
)(
implicit
reader: coll.pack.NarrowValueReader[T],
cbf: Factory[T, M[T]]
): Fu[M[T]] =
coll.distinct(key, selector.some, ReadConcern.Local, None)
coll.withReadPreference(readPreference).distinct(key, selector.some, ReadConcern.Local, None)

def findAndUpdate[D: BSONDocumentReader](
selector: coll.pack.Document,
Expand Down
4 changes: 2 additions & 2 deletions modules/forum/src/main/PostRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ final class PostRepo(val coll: Coll, filter: Filter = Safe)(
def sortQuery = $sort.createdAsc

def userIdsByTopicId(topicId: String): Fu[List[String]] =
coll.distinctEasy[User.ID, List]("userId", $doc("topicId" -> topicId))
coll.distinctEasy[User.ID, List]("userId", $doc("topicId" -> topicId), ReadPreference.secondaryPreferred)

def idsByTopicId(topicId: String): Fu[List[String]] =
coll.distinctEasy[String, List]("_id", $doc("topicId" -> topicId))
coll.distinctEasy[String, List]("_id", $doc("topicId" -> topicId), ReadPreference.secondaryPreferred)

def cursor =
coll.ext
Expand Down
17 changes: 7 additions & 10 deletions modules/game/src/main/GameRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,11 @@ final class GameRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
}

def playingRealtimeNoAi(user: User): Fu[List[Game.ID]] =
coll.distinctEasy[Game.ID, List](F.id, Query.nowPlaying(user.id) ++ Query.noAi ++ Query.clock(true))
coll.distinctEasy[Game.ID, List](
F.id,
Query.nowPlaying(user.id) ++ Query.noAi ++ Query.clock(true),
ReadPreference.secondaryPreferred
)

def lastPlayedPlayingId(userId: User.ID): Fu[Option[Game.ID]] =
coll
Expand Down Expand Up @@ -235,19 +239,12 @@ final class GameRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont

def setTv(id: ID) = coll.updateFieldUnchecked($id(id), F.tvAt, DateTime.now)

def setAnalysed(id: ID): Unit = {
coll.updateFieldUnchecked($id(id), F.analysed, true)
}
def setUnanalysed(id: ID): Unit = {
coll.updateFieldUnchecked($id(id), F.analysed, false)
}
def setAnalysed(id: ID): Unit = coll.updateFieldUnchecked($id(id), F.analysed, true)
def setUnanalysed(id: ID): Unit = coll.updateFieldUnchecked($id(id), F.analysed, false)

def isAnalysed(id: ID): Fu[Boolean] =
coll.exists($id(id) ++ Query.analysed(true))

def filterAnalysed(ids: Seq[ID]): Fu[Set[ID]] =
coll.distinctEasy[ID, Set]("_id", $inIds(ids) ++ $doc(F.analysed -> true))

def exists(id: ID) = coll.exists($id(id))

def tournamentId(id: ID): Fu[Option[String]] = coll.primitiveOne[String]($id(id), F.tournamentId)
Expand Down
6 changes: 2 additions & 4 deletions modules/pref/src/main/PrefApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,9 @@ final class PrefApi(
}

def unfollowableIds(userIds: List[User.ID]): Fu[Set[User.ID]] =
coll.distinctEasy[User.ID, Set](
coll.secondaryPreferred.distinctEasy[User.ID, Set](
"_id",
($inIds(userIds) ++ $doc(
"follow" -> false
))
($inIds(userIds) ++ $doc("follow" -> false))
)

def followableIds(userIds: List[User.ID]): Fu[Set[User.ID]] =
Expand Down
4 changes: 2 additions & 2 deletions modules/relation/src/main/RelationRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ final private class RelationRepo(coll: Coll)(implicit ec: scala.concurrent.Execu
rp: ReadPreference = ReadPreference.primary
): Fu[Set[ID]] =
coll
.withReadPreference(rp)
.distinctEasy[ID, Set](
"u1",
$doc(
"u2" -> userId,
"r" -> relation
)
),
rp
)

private def relating(userId: ID, relation: Relation): Fu[Set[ID]] =
Expand Down
7 changes: 4 additions & 3 deletions modules/report/src/main/ReportApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,13 @@ final class ReportApi(
)

def recentReportersOf(sus: Suspect): Fu[List[ReporterId]] =
coll.secondaryPreferred.distinctEasy[ReporterId, List](
coll.distinctEasy[ReporterId, List](
"atoms.by",
$doc(
"user" -> sus.user.id,
"atoms.0.at" $gt DateTime.now.minusDays(3)
)
),
ReadPreference.secondaryPreferred
) dmap (_ filterNot ReporterId.lichess.==)

def openAndRecentWithFilter(nb: Int, room: Option[Room]): Fu[List[Report.WithSuspect]] =
Expand Down Expand Up @@ -419,7 +420,7 @@ final class ReportApi(

def invalidate(selector: Bdoc): Funit =
coll
.distinctEasy[User.ID, List]("atoms.by", selector)
.distinctEasy[User.ID, List]("atoms.by", selector, ReadPreference.secondaryPreferred)
.map {
_ foreach cache.invalidate
}
Expand Down
19 changes: 11 additions & 8 deletions modules/security/src/main/CheckMail.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package lila.security

import scala.concurrent.duration._

import play.api.libs.ws.WSClient
import reactivemongo.api.ReadPreference

import lila.common.Domain
import lila.db.dsl._
Expand All @@ -28,14 +28,17 @@ final private class CheckMail(
true
}

// expensive
private[security] def fetchAllBlocked: Fu[List[String]] =
cache.coll.distinctEasy[String, List](
"_id",
$doc(
"_id" $regex s"^$prefix:",
"v" -> false
)
) map { ids =>
cache.coll
.distinctEasy[String, List](
"_id",
$doc(
"_id" $regex s"^$prefix:",
"v" -> false
),
ReadPreference.secondaryPreferred
) map { ids =>
val dropSize = prefix.size + 1
ids.map(_ drop dropSize)
}
Expand Down
3 changes: 2 additions & 1 deletion modules/security/src/main/Firewall.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package lila.security
import org.joda.time.DateTime
import play.api.mvc.RequestHeader
import scala.concurrent.duration._
import reactivemongo.api.ReadPreference

import lila.common.IpAddress
import lila.db.BSON.BSONJodaDateTimeHandler
Expand Down Expand Up @@ -46,7 +47,7 @@ final class Firewall(
coll.delete.one($inIds(ips.filter(validIp))).void >>- loadFromDb

private def loadFromDb: Funit =
coll.distinctEasy[String, Set]("_id", $empty).map { ips =>
coll.distinctEasy[String, Set]("_id", $empty, ReadPreference.secondaryPreferred).map { ips =>
current = ips
lila.mon.security.firewall.ip.update(ips.size)
}
Expand Down
14 changes: 7 additions & 7 deletions modules/security/src/main/PrintBan.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ final class PrintBan(coll: Coll)(implicit ec: scala.concurrent.ExecutionContext)
def blocks(hash: FingerHash): Boolean = current contains hash.value

def toggle(hash: FingerHash, block: Boolean): Funit = {
current = if (block) current + hash.value else current - hash.value
if (block)
coll.update
.one(
Expand All @@ -20,12 +21,11 @@ final class PrintBan(coll: Coll)(implicit ec: scala.concurrent.ExecutionContext)
upsert = true
)
.void
else coll.delete.one($id(hash.value))
} >> loadFromDb
else coll.delete.one($id(hash.value)).void
}

private def loadFromDb: Funit =
coll.distinctEasy[String, Set]("_id", $empty).map { hashes =>
current = hashes
lila.mon.security.firewall.prints.update(hashes.size)
}
coll.secondaryPreferred.distinctEasy[String, Set]("_id", $empty).map { hashes =>
current = hashes
lila.mon.security.firewall.prints.update(hashes.size)
}
}
8 changes: 5 additions & 3 deletions modules/security/src/main/SecurityApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import play.api.data.Forms._
import play.api.data.validation.{ Constraint, Valid => FormValid, Invalid, ValidationError }
import play.api.mvc.RequestHeader
import reactivemongo.api.bson._
import reactivemongo.api.ReadPreference
import scala.annotation.nowarn
import scala.concurrent.duration._

Expand Down Expand Up @@ -168,18 +169,19 @@ final class SecurityApi(
}

def ipUas(ip: IpAddress): Fu[List[String]] =
store.coll.distinctEasy[String, List]("ua", $doc("ip" -> ip.value))
store.coll.distinctEasy[String, List]("ua", $doc("ip" -> ip.value), ReadPreference.secondaryPreferred)

def printUas(fh: FingerHash): Fu[List[String]] =
store.coll.distinctEasy[String, List]("ua", $doc("fp" -> fh.value))
store.coll.distinctEasy[String, List]("ua", $doc("fp" -> fh.value), ReadPreference.secondaryPreferred)

private def recentUserIdsByField(field: String)(value: String): Fu[List[User.ID]] =
store.coll.distinctEasy[User.ID, List](
"user",
$doc(
field -> value,
"date" $gt DateTime.now.minusYears(1)
)
),
ReadPreference.secondaryPreferred
)
}

Expand Down
2 changes: 1 addition & 1 deletion modules/study/src/main/StudyRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ final class StudyRepo(private[study] val coll: Coll)(implicit ec: scala.concurre

// heavy AF. Only use for GDPR.
private[study] def allIdsByOwner(userId: User.ID): Fu[List[Study.Id]] =
coll.distinctEasy[Study.Id, List]("_id", selectOwnerId(userId))
coll.distinctEasy[Study.Id, List]("_id", selectOwnerId(userId), ReadPreference.secondaryPreferred)

def recentByContributor(userId: User.ID, nb: Int) =
coll
Expand Down
2 changes: 1 addition & 1 deletion modules/team/src/main/MemberRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class MemberRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCo

// expensive with thousands of members!
def userIdsByTeam(teamId: ID): Fu[Set[ID]] =
coll.distinctEasy[String, Set]("user", $doc("team" -> teamId))
coll.secondaryPreferred.distinctEasy[String, Set]("user", $doc("team" -> teamId))

def teamIdsByUser(userId: User.ID): Fu[Set[ID]] =
coll.distinctEasy[ID, Set]("team", $doc("user" -> userId))
Expand Down
2 changes: 1 addition & 1 deletion modules/team/src/main/TeamApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ final class TeamApi(
teamRepo.leads(teamId, userId)

def filterExistingIds(ids: Set[String]): Fu[Set[Team.ID]] =
teamRepo.coll.distinctEasy[Team.ID, Set]("_id", $doc("_id" $in ids))
teamRepo.coll.distinctEasy[Team.ID, Set]("_id", $doc("_id" $in ids), ReadPreference.secondaryPreferred)

def autocomplete(term: String, max: Int): Fu[List[Team]] =
teamRepo.coll.ext
Expand Down
8 changes: 6 additions & 2 deletions modules/team/src/main/TeamRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ final class TeamRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont

def enabled(id: Team.ID) = coll.one[Team]($id(id) ++ enabledSelect)

def enabledTeamIdsByLeader(userId: User.ID): Fu[List[String]] =
coll.distinctEasy[String, List]("_id", $doc("leaders" -> userId) ++ enabledSelect)
def enabledTeamIdsByLeader(userId: User.ID): Fu[List[Team.ID]] =
coll.distinctEasy[Team.ID, List](
"_id",
$doc("leaders" -> userId) ++ enabledSelect,
ReadPreference.secondaryPreferred
)

def byIdsSortPopular(ids: Seq[Team.ID]): Fu[List[Team]] =
coll.ext
Expand Down
11 changes: 6 additions & 5 deletions modules/timeline/src/main/UnsubApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ package lila.timeline
import reactivemongo.api.bson._

import lila.db.dsl._
import lila.user.User

final class UnsubApi(coll: Coll)(implicit ec: scala.concurrent.ExecutionContext) {

private def makeId(channel: String, userId: String) = s"$userId@$channel"
private def makeId(channel: String, userId: User.ID) = s"$userId@$channel"

private def select(channel: String, userId: String) = $id(makeId(channel, userId))
private def select(channel: String, userId: User.ID) = $id(makeId(channel, userId))

def set(channel: String, userId: String, v: Boolean): Funit = {
def set(channel: String, userId: User.ID, v: Boolean): Funit = {
if (v) coll.insert.one(select(channel, userId)).void
else coll.delete.one(select(channel, userId)).void
} recover {
case _: Exception => ()
}

def get(channel: String, userId: String): Fu[Boolean] =
def get(channel: String, userId: User.ID): Fu[Boolean] =
coll.countSel(select(channel, userId)) dmap (0 !=)

private def canUnsub(channel: String) = channel startsWith "forum:"

def filterUnsub(channel: String, userIds: List[String]): Fu[List[String]] =
def filterUnsub(channel: String, userIds: List[User.ID]): Fu[List[String]] =
canUnsub(channel) ?? coll.distinctEasy[String, List](
"_id",
$inIds(userIds.map { makeId(channel, _) })
Expand Down
31 changes: 16 additions & 15 deletions modules/user/src/main/UserRepo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
coll.primitiveOne[User.ID]($id(id), F.username)

def usernamesByIds(ids: List[ID]) =
coll.distinctEasy[String, List](F.username, $inIds(ids))
coll.distinctEasy[String, List](F.username, $inIds(ids), ReadPreference.secondaryPreferred)

def createdAtById(id: ID) =
coll.primitiveOne[DateTime]($id(id), F.createdAt)
Expand Down Expand Up @@ -491,9 +491,10 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
if (v) $doc(F.title -> Title.BOT)
else $doc(F.title -> $ne(Title.BOT))

private[user] def botIds = coll.secondaryPreferred.distinctEasy[String, Set](
private[user] def botIds = coll.distinctEasy[String, Set](
"_id",
botSelect(true) ++ enabledSelect
botSelect(true) ++ enabledSelect,
ReadPreference.secondaryPreferred
)

def getTitle(id: ID): Fu[Option[Title]] = coll.primitiveOne[Title]($id(id), F.title)
Expand Down Expand Up @@ -554,20 +555,19 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont

def langOf(id: ID): Fu[Option[String]] = coll.primitiveOne[String]($id(id), "lang")

// def idsSumToints(ids: Iterable[String]): Fu[Int] =
// ids.nonEmpty ?? coll.aggregateOne(
// Match($inIds(ids)),
// List(Group(BSONNull)(F.toints -> SumField(F.toints))),
// ReadPreference.secondaryPreferred
// ).map {
// _ flatMap { _.getAs[Int](F.toints) }
// }.map(~_)

def filterByEnabledPatrons(userIds: List[User.ID]): Fu[Set[User.ID]] =
coll.distinctEasy[String, Set](F.id, $inIds(userIds) ++ enabledSelect ++ patronSelect)
coll.distinctEasy[String, Set](
F.id,
$inIds(userIds) ++ enabledSelect ++ patronSelect,
ReadPreference.secondaryPreferred
)

def filterByRole(userIds: Seq[User.ID], role: String): Fu[Set[User.ID]] =
coll.distinctEasy[String, Set](F.id, $inIds(userIds) ++ enabledSelect ++ $doc(F.roles -> role))
coll.distinctEasy[String, Set](
F.id,
$inIds(userIds) ++ enabledSelect ++ $doc(F.roles -> role),
ReadPreference.secondaryPreferred
)

def userIdsWithRoles(roles: List[String]): Fu[Set[User.ID]] =
coll.distinctEasy[String, Set]("_id", $doc("roles" $in roles))
Expand Down Expand Up @@ -624,7 +624,8 @@ final class UserRepo(val coll: Coll)(implicit ec: scala.concurrent.ExecutionCont
def filterClosedOrInactiveIds(since: DateTime)(ids: Iterable[ID]): Fu[List[ID]] =
coll.distinctEasy[ID, List](
F.id,
$inIds(ids) ++ $or(disabledSelect, F.seenAt $lt since)
$inIds(ids) ++ $or(disabledSelect, F.seenAt $lt since),
ReadPreference.secondaryPreferred
)

private def newUser(
Expand Down
Loading

0 comments on commit 491a0bd

Please sign in to comment.