smaller caches initial capacity in dev mode
parent
7be8cff864
commit
b037980e15
|
@ -389,9 +389,8 @@ final class Tournament(
|
|||
}
|
||||
}
|
||||
|
||||
private val streamerCache = env.memo.cacheApi[Tour.ID, Set[UserModel.ID]]("tournament.streamers") {
|
||||
_.initialCapacity(64)
|
||||
.refreshAfterWrite(15.seconds)
|
||||
private val streamerCache = env.memo.cacheApi[Tour.ID, Set[UserModel.ID]](64, "tournament.streamers") {
|
||||
_.refreshAfterWrite(15.seconds)
|
||||
.maximumSize(64)
|
||||
.buildAsyncFuture { tourId =>
|
||||
env.tournament.tournamentRepo.isUnfinished(tourId) flatMap {
|
||||
|
|
|
@ -43,9 +43,8 @@ final class ChallengeApi(
|
|||
|
||||
def onlineByIdFor(id: Challenge.ID, dest: User) = repo.byIdFor(id, dest).dmap(_.filter(_.online))
|
||||
|
||||
val countInFor = cacheApi[User.ID, Int]("challenge.countInFor") {
|
||||
_.initialCapacity(65536)
|
||||
.expireAfterAccess(20 minutes)
|
||||
val countInFor = cacheApi[User.ID, Int](65536, "challenge.countInFor") {
|
||||
_.expireAfterAccess(20 minutes)
|
||||
.buildAsyncFuture(repo.countCreatedByDestId)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,9 +30,8 @@ final class ChatApi(
|
|||
// only use for public, multi-user chats - tournaments, simuls
|
||||
object cached {
|
||||
|
||||
private val cache = cacheApi[Chat.Id, UserChat]("chat.user") {
|
||||
_.initialCapacity(128)
|
||||
.expireAfterAccess(1 minute)
|
||||
private val cache = cacheApi[Chat.Id, UserChat](128, "chat.user") {
|
||||
_.expireAfterAccess(1 minute)
|
||||
.buildAsyncFuture(find)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,8 @@ final class EvalCacheApi(
|
|||
coll.delete.one($id(id)).void >>- cache.invalidate(id)
|
||||
}
|
||||
|
||||
private val cache = cacheApi[Id, Option[EvalCacheEntry]]("evalCache") {
|
||||
_.initialCapacity(65536)
|
||||
.expireAfterAccess(5 minutes)
|
||||
private val cache = cacheApi[Id, Option[EvalCacheEntry]](65536, "evalCache") {
|
||||
_.expireAfterAccess(5 minutes)
|
||||
.buildAsyncFuture(fetchAndSetAccess)
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,8 @@ final private class EvalCacheTruster(
|
|||
nbGamesBonus(user)
|
||||
}
|
||||
|
||||
private val userIdCache = cacheApi[User.ID, Option[TrustedUser]]("evalCache.userIdTrustCache") {
|
||||
_.initialCapacity(256)
|
||||
.expireAfterWrite(10 minutes)
|
||||
private val userIdCache = cacheApi[User.ID, Option[TrustedUser]](256, "evalCache.userIdTrustCache") {
|
||||
_.expireAfterWrite(10 minutes)
|
||||
.buildAsyncFuture { userId =>
|
||||
userRepo named userId map2 makeTrusted
|
||||
}
|
||||
|
|
|
@ -15,9 +15,8 @@ final private class FishnetRepo(
|
|||
|
||||
import BSONHandlers._
|
||||
|
||||
private val clientCache = cacheApi[Client.Key, Option[Client]]("fishnet.client") {
|
||||
_.initialCapacity(32)
|
||||
.expireAfterWrite(10 minutes)
|
||||
private val clientCache = cacheApi[Client.Key, Option[Client]](32, "fishnet.client") {
|
||||
_.expireAfterWrite(10 minutes)
|
||||
.buildAsyncFuture { key =>
|
||||
clientColl.one[Client](selectClient(key))
|
||||
}
|
||||
|
|
|
@ -35,9 +35,8 @@ final class Recent(
|
|||
} mkString ";"
|
||||
}
|
||||
|
||||
private val cache = cacheApi[String, List[MiniForumPost]]("forum.recent") {
|
||||
_.initialCapacity(2048)
|
||||
.expireAfterAccess(1 hour)
|
||||
private val cache = cacheApi[String, List[MiniForumPost]](2048, "forum.recent") {
|
||||
_.expireAfterAccess(1 hour)
|
||||
.buildAsyncFuture(fetch)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,8 @@ final class Cached(
|
|||
|
||||
def nbPlaying = nbPlayingCache.get _
|
||||
|
||||
private val nbPlayingCache = cacheApi[User.ID, Int]("game.nbPlaying") {
|
||||
_.initialCapacity(256)
|
||||
.expireAfterAccess(15 seconds)
|
||||
private val nbPlayingCache = cacheApi[User.ID, Int](256, "game.nbPlaying") {
|
||||
_.expireAfterAccess(15 seconds)
|
||||
.buildAsyncFuture { userId =>
|
||||
gameRepo.coll.countSel(Query nowPlaying userId)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ final class PlayTimeApi(
|
|||
creationCache.get(user.id).withTimeoutDefault(1 second, none)
|
||||
|
||||
// to avoid creating it twice
|
||||
private val creationCache = cacheApi[User.ID, Option[User.PlayTime]]("playTime") {
|
||||
private val creationCache = cacheApi[User.ID, Option[User.PlayTime]](64, "playTime") {
|
||||
_.expireAfterWrite(5 minutes)
|
||||
.buildAsyncFuture(computeNow)
|
||||
}
|
||||
|
|
|
@ -26,9 +26,8 @@ final class SeekApi(
|
|||
.sort($sort desc "createdAt")
|
||||
.cursor[Seek]()
|
||||
|
||||
private val cache = cacheApi[CacheKey, List[Seek]]("lobby.seek.list") {
|
||||
_.initialCapacity(2)
|
||||
.refreshAfterWrite(3 seconds)
|
||||
private val cache = cacheApi[CacheKey, List[Seek]](2, "lobby.seek.list") {
|
||||
_.refreshAfterWrite(3 seconds)
|
||||
.buildAsyncFuture {
|
||||
case ForAnon => allCursor.list(maxPerPage.value)
|
||||
case ForUser => allCursor.list()
|
||||
|
|
|
@ -3,23 +3,29 @@ package lila.memo
|
|||
import akka.actor.ActorSystem
|
||||
import com.github.benmanes.caffeine
|
||||
import com.github.blemale.scaffeine._
|
||||
import play.api.Mode
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
final class CacheApi(implicit ec: ExecutionContext, system: ActorSystem) {
|
||||
final class CacheApi(mode: Mode)(implicit ec: ExecutionContext, system: ActorSystem) {
|
||||
|
||||
private type Builder = Scaffeine[Any, Any]
|
||||
|
||||
def scaffeine: Builder = Scaffeine().scheduler(caffeine.cache.Scheduler.systemScheduler)
|
||||
|
||||
def apply[K, V](name: String)(build: Builder => AsyncLoadingCache[K, V]): AsyncLoadingCache[K, V] = {
|
||||
val cache = build(scaffeine)
|
||||
def apply[K, V](initialCapacity: Int, name: String)(
|
||||
build: Builder => AsyncLoadingCache[K, V]
|
||||
): AsyncLoadingCache[K, V] = {
|
||||
val actualCapacity =
|
||||
if (mode != Mode.Prod) math.sqrt(initialCapacity).toInt atLeast 1
|
||||
else initialCapacity
|
||||
val cache = build(scaffeine initialCapacity actualCapacity)
|
||||
monitor(name, cache)
|
||||
cache
|
||||
}
|
||||
|
||||
def unit[V](build: Builder => AsyncLoadingCache[Unit, V]): AsyncLoadingCache[Unit, V] = {
|
||||
build(scaffeine.initialCapacity(1))
|
||||
build(scaffeine initialCapacity 1)
|
||||
}
|
||||
|
||||
def monitor(name: String, cache: AsyncCache[_, _]): Unit =
|
||||
|
|
|
@ -14,6 +14,7 @@ final class MemoConfig(
|
|||
@Module
|
||||
final class Env(
|
||||
appConfig: Configuration,
|
||||
mode: play.api.Mode,
|
||||
db: lila.db.Db
|
||||
)(implicit ec: scala.concurrent.ExecutionContext, system: akka.actor.ActorSystem) {
|
||||
|
||||
|
|
|
@ -44,9 +44,8 @@ final class NotifyApi(
|
|||
unreadCountCache.put(_, fuccess(0))
|
||||
}
|
||||
|
||||
private val unreadCountCache = cacheApi[Notification.Notifies, Int]("notify.unreadCountCache") {
|
||||
_.initialCapacity(32768)
|
||||
.expireAfterAccess(20 minutes)
|
||||
private val unreadCountCache = cacheApi[Notification.Notifies, Int](32768, "notify.unreadCountCache") {
|
||||
_.expireAfterAccess(20 minutes)
|
||||
.buildAsyncFuture(repo.unreadNotificationsCount)
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,8 @@ final class OAuthServer(
|
|||
}
|
||||
|
||||
private val accessTokenCache =
|
||||
cacheApi[AccessToken.Id, Option[AccessToken.ForAuth]]("oauth.server.personal_access_token") {
|
||||
_.initialCapacity(16)
|
||||
.expireAfterWrite(5 minutes)
|
||||
cacheApi[AccessToken.Id, Option[AccessToken.ForAuth]](16, "oauth.server.personal_access_token") {
|
||||
_.expireAfterWrite(5 minutes)
|
||||
.buildAsyncFuture(fetchAccessToken)
|
||||
}
|
||||
|
||||
|
|
|
@ -191,9 +191,8 @@ final class PlaybanApi(
|
|||
|
||||
def getRageSit(userId: User.ID) = rageSitCache get userId
|
||||
|
||||
private val rageSitCache = cacheApi[User.ID, RageSit]("playban.ragesit") {
|
||||
private val rageSitCache = cacheApi[User.ID, RageSit](32768, "playban.ragesit") {
|
||||
_.expireAfterAccess(20 minutes)
|
||||
.initialCapacity(32768)
|
||||
.buildAsyncFuture { userId =>
|
||||
coll.primitiveOne[RageSit]($doc("_id" -> userId, "c" $exists true), "c").map(_ | RageSit.empty)
|
||||
}
|
||||
|
|
|
@ -17,9 +17,8 @@ final class PrefApi(
|
|||
|
||||
private def fetchPref(id: User.ID): Fu[Option[Pref]] = coll.ext.find($id(id)).one[Pref]
|
||||
|
||||
private val cache = cacheApi[User.ID, Option[Pref]]("pref.fetchPref") {
|
||||
_.initialCapacity(65536)
|
||||
.expireAfterAccess(10 minutes)
|
||||
private val cache = cacheApi[User.ID, Option[Pref]](65536, "pref.fetchPref") {
|
||||
_.expireAfterAccess(10 minutes)
|
||||
.buildAsyncFuture(fetchPref)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,8 @@ final private class GameJson(
|
|||
|
||||
private case class CacheKey(gameId: Game.ID, plies: Int, onlyLast: Boolean)
|
||||
|
||||
private val cache = cacheApi[CacheKey, JsObject]("puzzle.gameJson") {
|
||||
_.initialCapacity(1024)
|
||||
.expireAfterAccess(5 minutes)
|
||||
private val cache = cacheApi[CacheKey, JsObject](1024, "puzzle.gameJson") {
|
||||
_.expireAfterAccess(5 minutes)
|
||||
.maximumSize(1024)
|
||||
.buildAsyncFuture(generate)
|
||||
}
|
||||
|
|
|
@ -73,9 +73,8 @@ final class RelationApi(
|
|||
def fetchAreFriends(u1: ID, u2: ID): Fu[Boolean] =
|
||||
fetchFollows(u1, u2) >>& fetchFollows(u2, u1)
|
||||
|
||||
private val countFollowingCache = cacheApi[ID, Int]("relation.count.following") {
|
||||
_.initialCapacity(65536)
|
||||
.expireAfterAccess(10 minutes)
|
||||
private val countFollowingCache = cacheApi[ID, Int](65536, "relation.count.following") {
|
||||
_.expireAfterAccess(10 minutes)
|
||||
.maximumSize(65536)
|
||||
.buildAsyncFuture { userId =>
|
||||
coll.countSel($doc("u1" -> userId, "r" -> Follow))
|
||||
|
@ -86,9 +85,8 @@ final class RelationApi(
|
|||
|
||||
def reachedMaxFollowing(userId: ID): Fu[Boolean] = countFollowingCache get userId map (config.maxFollow <=)
|
||||
|
||||
private val countFollowersCache = cacheApi[ID, Int]("relation.count.followers") {
|
||||
_.initialCapacity(65536)
|
||||
.expireAfterAccess(10 minutes)
|
||||
private val countFollowersCache = cacheApi[ID, Int](65536, "relation.count.followers") {
|
||||
_.expireAfterAccess(10 minutes)
|
||||
.maximumSize(65536)
|
||||
.buildAsyncFuture { userId =>
|
||||
coll.countSel($doc("u2" -> userId, "r" -> Follow))
|
||||
|
|
|
@ -353,9 +353,8 @@ final class ReportApi(
|
|||
object accuracy {
|
||||
|
||||
private val cache =
|
||||
cacheApi[User.ID, Option[Accuracy]]("report.accuracy") {
|
||||
cacheApi[User.ID, Option[Accuracy]](512, "report.accuracy") {
|
||||
_.expireAfterWrite(24 hours)
|
||||
.initialCapacity(512)
|
||||
.buildAsyncFuture { reporterId =>
|
||||
coll.ext
|
||||
.find(
|
||||
|
|
|
@ -22,9 +22,8 @@ final class IpIntel(
|
|||
else if (contactEmail.value.isEmpty) fuccess(0)
|
||||
else cache get ip
|
||||
|
||||
private val cache = cacheApi[IpAddress, Int]("ipIntel") {
|
||||
_.initialCapacity(8192)
|
||||
.expireAfterWrite(3 days)
|
||||
private val cache = cacheApi[IpAddress, Int](8192, "ipIntel") {
|
||||
_.expireAfterWrite(3 days)
|
||||
.buildAsyncFuture { ip =>
|
||||
val url = s"https://check.getipintel.net/check.php?ip=$ip&contact=${contactEmail.value}"
|
||||
ws.url(url)
|
||||
|
|
|
@ -75,9 +75,8 @@ final class Env(
|
|||
lazy val pgnDump = wire[PgnDump]
|
||||
|
||||
lazy val lightStudyCache: LightStudyCache =
|
||||
cacheApi[Study.Id, Option[Study.LightStudy]]("study.lightStudyCache") {
|
||||
_.initialCapacity(512)
|
||||
.expireAfterWrite(20 minutes)
|
||||
cacheApi[Study.Id, Option[Study.LightStudy]](512, "study.lightStudyCache") {
|
||||
_.expireAfterWrite(20 minutes)
|
||||
.buildAsyncFuture(studyRepo.lightById)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,8 @@ final class Cached(
|
|||
|
||||
def invalidateTeamIds = teamIdsCache invalidate _
|
||||
|
||||
val nbRequests = cacheApi[User.ID, Int]("team.nbRequests") {
|
||||
val nbRequests = cacheApi[User.ID, Int](32768, "team.nbRequests") {
|
||||
_.expireAfterAccess(25 minutes)
|
||||
.initialCapacity(32768)
|
||||
.maximumSize(65536)
|
||||
.buildAsyncFuture[User.ID, Int] { userId =>
|
||||
teamRepo teamIdsByCreator userId flatMap requestRepo.countByTeams,
|
||||
|
|
|
@ -35,16 +35,14 @@ final private[tournament] class Cached(
|
|||
else ongoingRanking get tour.id
|
||||
|
||||
// only applies to ongoing tournaments
|
||||
private val ongoingRanking = cacheApi[Tournament.ID, Ranking]("tournament.ongoingRanking") {
|
||||
_.initialCapacity(64)
|
||||
.expireAfterWrite(3 seconds)
|
||||
private val ongoingRanking = cacheApi[Tournament.ID, Ranking](64, "tournament.ongoingRanking") {
|
||||
_.expireAfterWrite(3 seconds)
|
||||
.buildAsyncFuture(playerRepo.computeRanking)
|
||||
}
|
||||
|
||||
// only applies to finished tournaments
|
||||
private val finishedRanking = cacheApi[Tournament.ID, Ranking]("tournament.finishedRanking") {
|
||||
_.initialCapacity(1024)
|
||||
.expireAfterAccess(1 hour)
|
||||
private val finishedRanking = cacheApi[Tournament.ID, Ranking](1024, "tournament.finishedRanking") {
|
||||
_.expireAfterAccess(1 hour)
|
||||
.maximumSize(2048)
|
||||
.buildAsyncFuture(playerRepo.computeRanking)
|
||||
}
|
||||
|
@ -69,9 +67,8 @@ final private[tournament] class Cached(
|
|||
arena.Sheet(key.userId, _)
|
||||
}
|
||||
|
||||
private val cache = cacheApi[SheetKey, Sheet]("tournament.sheet") {
|
||||
_.initialCapacity(8192)
|
||||
.expireAfterAccess(3 minutes)
|
||||
private val cache = cacheApi[SheetKey, Sheet](8192, "tournament.sheet") {
|
||||
_.expireAfterAccess(3 minutes)
|
||||
.maximumSize(32768)
|
||||
.buildAsyncFuture(compute)
|
||||
}
|
||||
|
|
|
@ -234,9 +234,8 @@ final class JsonView(
|
|||
"win" -> s.scores.count(_.res == arena.Sheet.ResWin)
|
||||
)
|
||||
|
||||
private val cachableData = cacheApi[Tournament.ID, CachableData]("tournament.json.cachable") {
|
||||
_.initialCapacity(16)
|
||||
.expireAfterWrite(1 second)
|
||||
private val cachableData = cacheApi[Tournament.ID, CachableData](16, "tournament.json.cachable") {
|
||||
_.expireAfterWrite(1 second)
|
||||
.buildAsyncFuture { id =>
|
||||
for {
|
||||
tour <- tournamentRepo byId id
|
||||
|
@ -304,9 +303,8 @@ final class JsonView(
|
|||
.add("title" -> light.flatMap(_.title))
|
||||
}
|
||||
|
||||
private val podiumJsonCache = cacheApi[Tournament.ID, Option[JsArray]]("tournament.podiumJson") {
|
||||
_.initialCapacity(32)
|
||||
.expireAfterAccess(10 seconds)
|
||||
private val podiumJsonCache = cacheApi[Tournament.ID, Option[JsArray]](32, "tournament.podiumJson") {
|
||||
_.expireAfterAccess(10 seconds)
|
||||
.maximumSize(256)
|
||||
.buildAsyncFuture { id =>
|
||||
tournamentRepo finishedById id flatMap {
|
||||
|
@ -351,9 +349,8 @@ final class JsonView(
|
|||
"p" -> Json.arr(u1, u2)
|
||||
)
|
||||
|
||||
private val teamStandingCache = cacheApi[Tournament.ID, JsArray]("tournament.teamStanding") {
|
||||
_.initialCapacity(4)
|
||||
.expireAfterWrite(1 second)
|
||||
private val teamStandingCache = cacheApi[Tournament.ID, JsArray](4, "tournament.teamStanding") {
|
||||
_.expireAfterWrite(1 second)
|
||||
.buildAsyncFuture { id =>
|
||||
tournamentRepo.teamBattleOf(id) flatMap {
|
||||
_.fold(fuccess(JsArray())) { battle =>
|
||||
|
@ -384,9 +381,8 @@ final class JsonView(
|
|||
)
|
||||
}
|
||||
|
||||
private val teamInfoCache = cacheApi[(Tournament.ID, TeamID), Option[JsObject]]("tournament.teamInfo") {
|
||||
_.initialCapacity(4)
|
||||
.expireAfterWrite(5 seconds)
|
||||
private val teamInfoCache = cacheApi[(Tournament.ID, TeamID), Option[JsObject]](4, "tournament.teamInfo") {
|
||||
_.expireAfterWrite(5 seconds)
|
||||
.maximumSize(32)
|
||||
.buildAsyncFuture {
|
||||
case (tourId, teamId) =>
|
||||
|
|
|
@ -452,9 +452,8 @@ final class TournamentApi(
|
|||
socket.reload(tour.id) >>- publish()
|
||||
}
|
||||
|
||||
private val tournamentTopCache = cacheApi[Tournament.ID, TournamentTop]("tournament.top") {
|
||||
_.initialCapacity(16)
|
||||
.refreshAfterWrite(3 second)
|
||||
private val tournamentTopCache = cacheApi[Tournament.ID, TournamentTop](16, "tournament.top") {
|
||||
_.refreshAfterWrite(3 second)
|
||||
.expireAfterAccess(5 minutes)
|
||||
.maximumSize(64)
|
||||
.buildAsyncFuture { id =>
|
||||
|
|
|
@ -33,15 +33,13 @@ final class TournamentStandingApi(
|
|||
else computeMaybe(tour.id, page)
|
||||
} else compute(tour, page)
|
||||
|
||||
private val first = cacheApi[Tournament.ID, JsObject]("tournament.page.first") {
|
||||
_.initialCapacity(16)
|
||||
.expireAfterWrite(1 second)
|
||||
private val first = cacheApi[Tournament.ID, JsObject](16, "tournament.page.first") {
|
||||
_.expireAfterWrite(1 second)
|
||||
.buildAsyncFuture { compute(_, 1) }
|
||||
}
|
||||
|
||||
private val createdCache = cacheApi[(Tournament.ID, Int), JsObject]("tournament.page.createdCache") {
|
||||
_.initialCapacity(2)
|
||||
.expireAfterWrite(15 second)
|
||||
private val createdCache = cacheApi[(Tournament.ID, Int), JsObject](2, "tournament.page.createdCache") {
|
||||
_.expireAfterWrite(15 second)
|
||||
.buildAsyncFuture {
|
||||
case (tourId, page) => computeMaybe(tourId, page)
|
||||
}
|
||||
|
|
|
@ -212,9 +212,8 @@ final private[video] class VideoApi(
|
|||
|
||||
private val max = 25
|
||||
|
||||
private val pathsCache = cacheApi[List[Tag], List[TagNb]]("video.paths") {
|
||||
_.initialCapacity(32)
|
||||
.expireAfterAccess(10 minutes)
|
||||
private val pathsCache = cacheApi[List[Tag], List[TagNb]](32, "video.paths") {
|
||||
_.expireAfterAccess(10 minutes)
|
||||
.buildAsyncFuture { filterTags =>
|
||||
val allPaths =
|
||||
if (filterTags.isEmpty) allPopular map { tags =>
|
||||
|
|
Loading…
Reference in New Issue