replace spray caching with AsyncCache2 in many places

new-cache
Thibault Duplessis 2017-01-26 23:22:12 +01:00
parent c39f5d20b3
commit 1986cb3235
29 changed files with 154 additions and 110 deletions

View File

@ -40,7 +40,7 @@ object Account extends LilaController {
relationEnv.api.countFollowing(me.id) zip
Env.pref.api.getPref(me) zip
lila.game.GameRepo.urgentGames(me) zip
Env.challenge.api.countInFor(me.id) map {
Env.challenge.api.countInFor.get(me.id) map {
case ((((nbFollowers, nbFollowing), prefs), povs), nbChallenges) =>
Env.current.bus.publish(lila.user.User.Active(me), 'userActive)
Ok {

View File

@ -291,7 +291,7 @@ private[controllers] trait LilaController
Env.user.lightUserApi preloadUser me
getOnlineFriends(me) zip
Env.team.api.nbRequests(me.id) zip
Env.challenge.api.countInFor(me.id) zip
Env.challenge.api.countInFor.get(me.id) zip
Env.notifyModule.api.unreadCount(Notifies(me.id)).map(_.value)
}
else fuccess {

View File

@ -71,9 +71,9 @@ object Lobby extends LilaController {
private def renderCtx(implicit ctx: Context): Fu[Html] = Env.current.preloader(
posts = Env.forum.recent(ctx.me, Env.team.cached.teamIds),
tours = Env.tournament.cached promotable true,
events = Env.event.api promotable true,
simuls = Env.simul allCreatedFeaturable true
tours = Env.tournament.cached.promotable.get,
events = Env.event.api.promotable.get,
simuls = Env.simul.allCreatedFeaturable.get
) map (html.lobby.home.apply _).tupled
private def renderRequestKey(r: RequestKey): Fu[Html] = renderCtx {

View File

@ -30,7 +30,7 @@ object Simul extends LilaController {
}
private def fetchSimuls =
env.allCreated(true) zip env.repo.allStarted zip env.repo.allFinished(30)
env.allCreated.get zip env.repo.allStarted zip env.repo.allFinished(30)
def show(id: String) = Open { implicit ctx =>
env.repo find id flatMap {

View File

@ -67,7 +67,7 @@ object User extends LilaController {
val max = 50
negotiate(
html = notFound,
api = _ => env.cached top50Online true map { list =>
api = _ => env.cached.top50Online.get map { list =>
Ok(Json.toJson(list.take(getInt("nb").fold(10)(_ min max)).map(env.jsonView(_))))
})
}
@ -162,7 +162,7 @@ object User extends LilaController {
// }
// }
tourneyWinners Env.tournament.winners.all.map(_.top)
online env.cached top50Online true
online env.cached.top50Online.get
_ <- Env.user.lightUserApi preloadMany tourneyWinners.map(_.userId)
res <- negotiate(
html = fuccess(Ok(html.user.list(

View File

@ -1,10 +1,12 @@
package lila.blog
import io.prismic._
import lila.memo.AsyncCache
import scala.concurrent.duration._
final class BlogApi(prismicUrl: String, collection: String) {
final class BlogApi(
asyncCache: lila.memo.AsyncCache2.Builder,
prismicUrl: String,
collection: String) {
def recent(api: Api, ref: Option[String], nb: Int): Fu[Option[Response]] =
api.forms(collection).ref(resolveRef(api)(ref) | api.master.ref)
@ -38,12 +40,12 @@ final class BlogApi(prismicUrl: String, collection: String) {
case _ => logger info message
}
private val fetchPrismicApi = AsyncCache.single[Api](
private val fetchPrismicApi = asyncCache.single[Api](
name = "blogApi.fetchPrismicApi",
f = Api.get(prismicUrl, cache = cache, logger = prismicLogger),
timeToLive = 10 seconds)
expireAfter = _.ExpireAfterWrite(15 seconds))
def prismicApi = fetchPrismicApi(true)
def prismicApi = fetchPrismicApi.get
}
object BlogApi {

View File

@ -7,6 +7,7 @@ import lila.common.PimpedConfig._
final class Env(
config: Config,
scheduler: lila.common.Scheduler,
asyncCache: lila.memo.AsyncCache2.Builder,
notifyApi: lila.notify.NotifyApi)(implicit system: akka.actor.ActorSystem) {
private val PrismicApiUrl = config getString "prismic.api_url"
@ -17,6 +18,7 @@ final class Env(
lazy val api = new BlogApi(
prismicUrl = PrismicApiUrl,
asyncCache = asyncCache,
collection = PrismicCollection)
lazy val lastPostCache = new LastPostCache(api, LastPostCacheTtl, PrismicCollection)
@ -38,6 +40,7 @@ object Env {
lazy val current: Env = "blog" boot new Env(
config = lila.common.PlayApp loadConfig "blog",
scheduler = lila.common.PlayApp.scheduler,
asyncCache = lila.memo.Env.current.asyncCache,
notifyApi = lila.notify.Env.current.api)(
lila.common.PlayApp.system)
}

View File

@ -2,11 +2,11 @@ package lila.challenge
import akka.actor._
import org.joda.time.DateTime
import scala.concurrent.duration._
import lila.game.{ Game, Pov, GameRepo }
import lila.hub.actorApi.map.Tell
import lila.hub.actorApi.SendTo
import lila.memo.AsyncCache
import lila.user.{ User, UserRepo }
final class ChallengeApi(
@ -17,6 +17,7 @@ final class ChallengeApi(
maxPlaying: Int,
socketHub: ActorRef,
userRegister: ActorSelection,
asyncCache: lila.memo.AsyncCache2.Builder,
lilaBus: lila.common.Bus) {
import Challenge._
@ -29,38 +30,40 @@ final class ChallengeApi(
case true => fuccess(false)
case false => {
repo like c flatMap { _ ?? repo.cancel }
} >> (repo insert c) >> uncacheAndNotify(c) >>- {
} >> (repo insert c) >>- {
uncacheAndNotify(c)
lilaBus.publish(Event.Create(c), 'challenge)
} inject true
}
def byId = repo byId _
val countInFor = AsyncCache(
val countInFor = asyncCache.clearable(
name = "challenge.countInFor",
f = repo.countCreatedByDestId,
maxCapacity = 20000)
expireAfter = _.ExpireAfterAccess(12 minutes))
def createdByChallengerId = repo createdByChallengerId _
def createdByDestId = repo createdByDestId _
def cancel(c: Challenge) = (repo cancel c) >> uncacheAndNotify(c)
def cancel(c: Challenge) = (repo cancel c) >>- uncacheAndNotify(c)
private def offline(c: Challenge) = (repo offline c) >> uncacheAndNotify(c)
private def offline(c: Challenge) = (repo offline c) >>- uncacheAndNotify(c)
private[challenge] def ping(id: Challenge.ID): Funit = repo statusById id flatMap {
case Some(Status.Created) => repo setSeen id
case Some(Status.Offline) => (repo setSeenAgain id) >> byId(id).flatMap { _ ?? uncacheAndNotify }
case Some(Status.Offline) => (repo setSeenAgain id) >> byId(id).map { _ foreach uncacheAndNotify }
case _ => fuccess(socketReload(id))
}
def decline(c: Challenge) = (repo decline c) >> uncacheAndNotify(c)
def decline(c: Challenge) = (repo decline c) >>- uncacheAndNotify(c)
def accept(c: Challenge, user: Option[User]): Fu[Option[Pov]] =
joiner(c, user).flatMap {
case None => fuccess(None)
case Some(pov) => (repo accept c) >> uncacheAndNotify(c) >>- {
case Some(pov) => (repo accept c) >>- {
uncacheAndNotify(c)
lilaBus.publish(Event.Accept(c, user.map(_.id)), 'challenge)
} inject pov.some
}
@ -111,22 +114,20 @@ final class ChallengeApi(
}
private def remove(c: Challenge) =
repo.remove(c.id) >> uncacheAndNotify(c)
repo.remove(c.id) >>- uncacheAndNotify(c)
private def uncacheAndNotify(c: Challenge) = {
(c.destUserId ?? countInFor.remove) >>-
(c.destUserId ?? notify) >>-
(c.challengerUserId ?? notify) >>-
socketReload(c.id)
private def uncacheAndNotify(c: Challenge): Unit = {
c.destUserId ?? countInFor.invalidate
c.destUserId ?? notify
c.challengerUserId ?? notify
socketReload(c.id)
}
private def socketReload(id: Challenge.ID) {
private def socketReload(id: Challenge.ID): Unit =
socketHub ! Tell(id, Socket.Reload)
}
private def notify(userId: User.ID) {
private def notify(userId: User.ID): Unit =
allFor(userId) foreach { all =>
userRegister ! SendTo(userId, lila.socket.Socket.makeMessage("challenges", jsonView(all)))
}
}
}

View File

@ -19,6 +19,7 @@ final class Env(
isOnline: lila.user.User.ID => Boolean,
hub: lila.hub.Env,
db: lila.db.Env,
asyncCache: lila.memo.AsyncCache2.Builder,
scheduler: lila.common.Scheduler) {
private val settings = new {
@ -58,6 +59,7 @@ final class Env(
maxPlaying = MaxPlaying,
socketHub = socketHub,
userRegister = hub.actor.userRegister,
asyncCache = asyncCache,
lilaBus = system.lilaBus)
private lazy val repo = new ChallengeRepo(
@ -82,5 +84,6 @@ object Env {
lightUser = lila.user.Env.current.lightUserSync,
isOnline = lila.user.Env.current.isOnline,
db = lila.db.Env.current,
asyncCache = lila.memo.Env.current.asyncCache,
scheduler = lila.common.PlayApp.scheduler)
}

View File

@ -4,7 +4,6 @@ import org.joda.time.DateTime
import scala.concurrent.duration._
import lila.db.dsl._
import lila.memo.AsyncCache
import lila.notify.{ Notification, NotifyApi }
import lila.security.Granter
import lila.user.{ User, UserRepo }
@ -13,16 +12,17 @@ final class CoachApi(
coachColl: Coll,
reviewColl: Coll,
photographer: Photographer,
asyncCache: lila.memo.AsyncCache2.Builder,
notifyApi: NotifyApi) {
import BsonHandlers._
private val cache = AsyncCache.single[List[Coach]](
private val cache = asyncCache.single[List[Coach]](
name = "coach.list",
f = coachColl.find($empty).list[Coach](),
timeToLive = 10 minutes)
expireAfter = _.ExpireAfterWrite(30 minutes))
private def all = cache(true)
private def all = cache.get
def byId(id: Coach.Id): Fu[Option[Coach]] = all.map(_.find(_.id == id))
@ -36,7 +36,7 @@ final class CoachApi(
def findOrInit(user: User): Fu[Option[Coach.WithUser]] = Granter(_.Coach)(user) ?? {
find(user) orElse {
val c = Coach.WithUser(Coach make user, user)
coachColl.insert(c.coach) >> cache.remove(true) inject c.some
coachColl.insert(c.coach) >>- cache.refresh inject c.some
}
}
@ -59,10 +59,10 @@ final class CoachApi(
$id(c.coach.id),
data(c.coach),
upsert = true
).void >> cache.clear
).void >>- cache.refresh
def setNbReviews(id: Coach.Id, nb: Int): Funit =
coachColl.update($id(id), $set("nbReviews" -> nb)).void >> cache.clear
coachColl.update($id(id), $set("nbReviews" -> nb)).void >>- cache.refresh
private[coach] def toggleApproved(username: String, value: Boolean): Fu[String] =
find(username) flatMap {
@ -70,16 +70,16 @@ final class CoachApi(
case Some(c) => coachColl.update(
$id(c.coach.id),
$set("approved" -> value)
) >> cache.clear inject "Done!"
) >>- cache.refresh inject "Done!"
}
def uploadPicture(c: Coach.WithUser, picture: Photographer.Uploaded): Funit =
photographer(c.coach.id, picture).flatMap { pic =>
coachColl.update($id(c.coach.id), $set("picturePath" -> pic.path))
} >> cache.clear
coachColl.update($id(c.coach.id), $set("picturePath" -> pic.path)).void
} >>- cache.refresh
def deletePicture(c: Coach.WithUser): Funit =
coachColl.update($id(c.coach.id), $unset("picturePath")) >> cache.clear
coachColl.update($id(c.coach.id), $unset("picturePath")).void >>- cache.refresh
private def withUser(user: User)(coach: Coach): Coach.WithUser =
Coach.WithUser(coach, user)

View File

@ -5,6 +5,7 @@ import com.typesafe.config.Config
final class Env(
config: Config,
notifyApi: lila.notify.NotifyApi,
asyncCache: lila.memo.AsyncCache2.Builder,
db: lila.db.Env) {
private val CollectionCoach = config getString "collection.coach"
@ -21,6 +22,7 @@ final class Env(
coachColl = coachColl,
reviewColl = reviewColl,
photographer = photographer,
asyncCache = asyncCache,
notifyApi = notifyApi)
lazy val pager = new CoachPager(api)
@ -38,5 +40,6 @@ object Env {
lazy val current: Env = "coach" boot new Env(
config = lila.common.PlayApp loadConfig "coach",
notifyApi = lila.notify.Env.current.api,
asyncCache = lila.memo.Env.current.asyncCache,
db = lila.db.Env.current)
}

View File

@ -6,13 +6,14 @@ import com.typesafe.config.Config
final class Env(
config: Config,
db: lila.db.Env,
asyncCache: lila.memo.AsyncCache2.Builder,
system: ActorSystem) {
private val CollectionEvent = config getString "collection.event"
private lazy val eventColl = db(CollectionEvent)
lazy val api = new EventApi(coll = eventColl)
lazy val api = new EventApi(coll = eventColl, asyncCache = asyncCache)
}
object Env {
@ -20,5 +21,6 @@ object Env {
lazy val current = "event" boot new Env(
config = lila.common.PlayApp loadConfig "event",
db = lila.db.Env.current,
asyncCache = lila.memo.Env.current.asyncCache,
system = lila.common.PlayApp.system)
}

View File

@ -6,13 +6,16 @@ import scala.concurrent.duration._
import lila.db.dsl._
import lila.memo._
final class EventApi(coll: Coll) {
final class EventApi(
coll: Coll,
asyncCache: lila.memo.AsyncCache2.Builder) {
import BsonHandlers._
val promotable = AsyncCache.single(
val promotable = asyncCache.single(
name = "event.promotable",
fetchPromotable, timeToLive = 5 minutes)
fetchPromotable,
expireAfter = _.ExpireAfterWrite(5 minutes))
def fetchPromotable: Fu[List[Event]] = coll.find($doc(
"enabled" -> true,
@ -37,12 +40,12 @@ final class EventApi(coll: Coll) {
}
def update(old: Event, data: EventForm.Data) =
coll.update($id(old.id), data update old) >> promotable.clear
coll.update($id(old.id), data update old) >>- promotable.refresh
def createForm = EventForm.form
def create(data: EventForm.Data, userId: String): Fu[Event] = {
val event = data make userId
coll.insert(event) >> promotable.clear inject event
coll.insert(event) >>- promotable.refresh inject event
}
}

View File

@ -3,17 +3,18 @@ package lila.game
import scala.concurrent.duration._
import lila.db.dsl._
import lila.memo.{ AsyncCache, MongoCache, ExpireSetMemo }
import lila.memo.{ MongoCache, ExpireSetMemo }
import lila.user.User
final class Cached(
coll: Coll,
asyncCache: lila.memo.AsyncCache2.Builder,
mongoCache: MongoCache.Builder) {
def nbImportedBy(userId: String): Fu[Int] = nbImportedCache(userId)
def clearNbImportedByCache = nbImportedCache remove _
def nbPlaying(userId: String): Fu[Int] = countShortTtl(Query nowPlaying userId)
def nbPlaying(userId: String): Fu[Int] = countShortTtl.get(Query nowPlaying userId)
def nbTotal: Fu[Int] = countCache($empty)
@ -23,10 +24,10 @@ final class Cached(
val isRematch = new ExpireSetMemo(3.hours)
private val countShortTtl = AsyncCache[Bdoc, Int](
private val countShortTtl = asyncCache.multi[Bdoc, Int](
name = "game.countShortTtl",
f = coll.countSel,
timeToLive = 5.seconds)
expireAfter = _.ExpireAfterWrite(5.seconds))
private val nbImportedCache = mongoCache[User.ID, Int](
prefix = "game:imported",

View File

@ -14,6 +14,7 @@ final class Env(
getLightUser: lila.common.LightUser.GetterSync,
appPath: String,
isProd: Boolean,
asyncCache: lila.memo.AsyncCache2.Builder,
scheduler: lila.common.Scheduler) {
private val settings = new {
@ -39,6 +40,7 @@ final class Env(
lazy val cached = new Cached(
coll = gameColl,
asyncCache = asyncCache,
mongoCache = mongoCache)
lazy val paginator = new PaginatorBuilder(
@ -94,5 +96,6 @@ object Env {
getLightUser = lila.user.Env.current.lightUserSync,
appPath = play.api.Play.current.path.getCanonicalPath,
isProd = lila.common.PlayApp.isProd,
asyncCache = lila.memo.Env.current.asyncCache,
scheduler = lila.common.PlayApp.scheduler)
}

View File

@ -34,7 +34,7 @@ final class PublicChat(
}
private def fetchVisibleSimuls: Fu[List[Simul]] = {
simulEnv.allCreated(true) zip
simulEnv.allCreated.get zip
simulEnv.repo.allStarted zip
simulEnv.repo.allFinished(3) map {
case ((created, started), finished) =>

View File

@ -7,20 +7,21 @@ import akka.pattern.ask
import org.joda.time.DateTime
import lila.db.dsl._
import Puzzle.{BSONFields => F}
import Puzzle.{ BSONFields => F }
private[puzzle] final class Daily(
coll: Coll,
renderer: ActorSelection,
asyncCache: lila.memo.AsyncCache2.Builder,
scheduler: Scheduler) {
private val cache =
lila.memo.AsyncCache.single[Option[DailyPuzzle]](
asyncCache.single[Option[DailyPuzzle]](
name = "puzzle.daily",
f = find,
timeToLive = 10 minutes)
expireAfter = _.ExpireAfterWrite(10 minutes))
def apply(): Fu[Option[DailyPuzzle]] = cache apply true
def apply: Fu[Option[DailyPuzzle]] = cache.get
private def find: Fu[Option[DailyPuzzle]] = (findCurrent orElse findNew) recover {
case e: Exception =>
@ -28,9 +29,7 @@ private[puzzle] final class Daily(
none
} flatMap {
case Some(puzzle) => makeDaily(puzzle)
case None =>
scheduler.scheduleOnce(10.seconds)(cache.clear)
fuccess(none)
case None => fuccess(none)
}
private def makeDaily(puzzle: Puzzle): Fu[Option[DailyPuzzle]] = {

View File

@ -9,6 +9,7 @@ final class Env(
config: Config,
renderer: ActorSelection,
lightUser: lila.common.LightUser.GetterSync,
asyncCache: lila.memo.AsyncCache2.Builder,
system: ActorSystem,
lifecycle: play.api.inject.ApplicationLifecycle) {
@ -26,7 +27,7 @@ final class Env(
private val db = new lila.db.Env("puzzle", config getConfig "mongodb", lifecycle)
private lazy val gameJson = new GameJson(lightUser)
private lazy val gameJson = new GameJson(asyncCache, lightUser)
lazy val jsonView = new JsonView(
gameJson,
@ -39,6 +40,7 @@ final class Env(
voteColl = voteColl,
headColl = headColl,
puzzleIdMin = PuzzleIdMin,
asyncCache = asyncCache,
apiToken = ApiToken)
lazy val finisher = new Finisher(
@ -57,6 +59,7 @@ final class Env(
lazy val daily = new Daily(
puzzleColl,
renderer,
asyncCache = asyncCache,
system.scheduler
).apply _
@ -81,6 +84,7 @@ object Env {
config = lila.common.PlayApp loadConfig "puzzle",
renderer = lila.hub.Env.current.actor.renderer,
lightUser = lila.user.Env.current.lightUserSync,
asyncCache = lila.memo.Env.current.asyncCache,
system = lila.common.PlayApp.system,
lifecycle = lila.common.PlayApp.lifecycle)
}

View File

@ -1,22 +1,25 @@
package lila.puzzle
import play.api.libs.json._
import scala.concurrent.duration._
import lila.common.PimpedJson._
import lila.game.{ Game, GameRepo, PerfPicker }
import lila.tree.Node.partitionTreeJsonWriter
private final class GameJson(
lightUser: lila.common.LightUser.GetterSync) {
asyncCache: lila.memo.AsyncCache2.Builder,
lightUser: lila.common.LightUser.GetterSync) {
case class CacheKey(gameId: Game.ID, plies: Int)
private val cache = lila.memo.AsyncCache[CacheKey, JsObject](
private val cache = asyncCache.multi[CacheKey, JsObject](
name = "puzzle.gameJson",
f = generate,
maxCapacity = 500)
expireAfter = _.ExpireAfterAccess(1 hour),
maxCapacity = 1024)
def apply(gameId: Game.ID, plies: Int): Fu[JsObject] = cache(CacheKey(gameId, plies))
def apply(gameId: Game.ID, plies: Int): Fu[JsObject] = cache get CacheKey(gameId, plies)
def generate(ck: CacheKey): Fu[JsObject] = ck match {
case CacheKey(gameId, plies) =>

View File

@ -15,6 +15,7 @@ private[puzzle] final class PuzzleApi(
voteColl: Coll,
headColl: Coll,
puzzleIdMin: PuzzleId,
asyncCache: lila.memo.AsyncCache2.Builder,
apiToken: String) {
import Puzzle.puzzleBSONHandler
@ -32,9 +33,10 @@ private[puzzle] final class PuzzleApi(
private def lastId: Fu[Int] = lila.db.Util findNextId puzzleColl map (_ - 1)
val cachedLastId = lila.memo.AsyncCache.single(
val cachedLastId = asyncCache.single(
name = "puzzle.lastId",
lastId, timeToLive = 5 minutes)
lastId,
expireAfter = _.ExpireAfterWrite(20 minutes))
def importOne(json: JsValue, token: String): Fu[PuzzleId] =
if (token != apiToken) fufail("Invalid API token")

View File

@ -55,7 +55,7 @@ private[puzzle] final class Selector(
private def newPuzzleForUser(user: User): Fu[Option[Puzzle]] = {
val rating = user.perfs.puzzle.intRating min 2300 max 900
val step = toleranceStepFor(rating)
(api.head.find(user) zip api.puzzle.cachedLastId(true)) flatMap {
(api.head.find(user) zip api.puzzle.cachedLastId.get) flatMap {
case (opHead, maxId) =>
val lastId = opHead match {
case Some(PuzzleHead(_, _, l)) if l < maxId - 500 => l

View File

@ -20,7 +20,8 @@ final class Env(
hub: lila.hub.Env,
lightUser: lila.common.LightUser.Getter,
onGameStart: String => Unit,
isOnline: String => Boolean) {
isOnline: String => Boolean,
asyncCache: lila.memo.AsyncCache2.Builder) {
private val settings = new {
val CollectionSimul = config getString "collection.simul"
@ -47,7 +48,8 @@ final class Env(
userRegister = hub.actor.userRegister,
lobby = hub.socket.lobby,
onGameStart = onGameStart,
sequencers = sequencerMap)
sequencers = sequencerMap,
asyncCache = asyncCache)
lazy val forms = new DataForm
@ -80,7 +82,8 @@ final class Env(
case move: lila.hub.actorApi.round.MoveEvent =>
move.simulId foreach { simulId =>
move.opponentUserId foreach { opId =>
hub.actor.userRegister ! lila.hub.actorApi.SendTo(opId,
hub.actor.userRegister ! lila.hub.actorApi.SendTo(
opId,
lila.socket.Socket.makeMessage("simulPlayerMove", move.gameId))
}
}
@ -89,13 +92,15 @@ final class Env(
def isHosting(userId: String): Fu[Boolean] = api.currentHostIds map (_ contains userId)
val allCreated = lila.memo.AsyncCache.single(
val allCreated = asyncCache.single(
name = "simul.allCreated",
repo.allCreated, timeToLive = CreatedCacheTtl)
repo.allCreated,
expireAfter = _.ExpireAfterWrite(CreatedCacheTtl))
val allCreatedFeaturable = lila.memo.AsyncCache.single(
val allCreatedFeaturable = asyncCache.single(
name = "simul.allCreatedFeaturable",
repo.allCreatedFeaturable, timeToLive = CreatedCacheTtl)
repo.allCreatedFeaturable,
expireAfter = _.ExpireAfterWrite(CreatedCacheTtl))
def version(tourId: String): Fu[Int] =
socketHub ? Ask(tourId, GetVersion) mapTo manifest[Int]
@ -121,5 +126,6 @@ object Env {
hub = lila.hub.Env.current,
lightUser = lila.user.Env.current.lightUser,
onGameStart = lila.game.Env.current.onStart,
isOnline = lila.user.Env.current.isOnline)
isOnline = lila.user.Env.current.isOnline,
asyncCache = lila.memo.Env.current.asyncCache)
}

View File

@ -11,7 +11,6 @@ import lila.game.{ Game, GameRepo }
import lila.hub.actorApi.lobby.ReloadSimuls
import lila.hub.actorApi.map.Tell
import lila.hub.actorApi.timeline.{ Propagate, SimulCreate, SimulJoin }
import lila.memo.AsyncCache
import lila.socket.actorApi.SendToFlag
import lila.user.{ User, UserRepo }
import makeTimeout.short
@ -26,14 +25,15 @@ private[simul] final class SimulApi(
timeline: ActorSelection,
userRegister: ActorSelection,
lobby: ActorSelection,
repo: SimulRepo) {
repo: SimulRepo,
asyncCache: lila.memo.AsyncCache2.Builder) {
def currentHostIds: Fu[Set[String]] = currentHostIdsCache apply true
def currentHostIds: Fu[Set[String]] = currentHostIdsCache.get
private val currentHostIdsCache = AsyncCache.single[Set[String]](
private val currentHostIdsCache = asyncCache.single[Set[String]](
name = "simul.currentHostIds",
f = repo.allStarted map (_ map (_.hostId) toSet),
timeToLive = 10 minutes)
expireAfter = _.ExpireAfterAccess(10 minutes))
def create(setup: SimulSetup, me: User): Fu[Simul] = {
val simul = Simul.make(
@ -90,7 +90,7 @@ private[simul] final class SimulApi(
}
}
} flatMap update
} >> currentHostIdsCache.remove(true)
} >>- currentHostIdsCache.refresh
}
}
}
@ -122,7 +122,8 @@ private[simul] final class SimulApi(
game.id,
_.finish(game.status, game.winnerUserId, game.turns)
)
update(simul2) >> currentHostIdsCache.remove(true) >>- {
update(simul2) >>- {
currentHostIdsCache.refresh
if (simul2.isFinished) userRegister ! lila.hub.actorApi.SendTo(
simul2.hostId,
lila.socket.Socket.makeMessage("simulEnd", Json.obj(

View File

@ -5,6 +5,7 @@ import scala.concurrent.duration._
import lila.memo._
private[tournament] final class Cached(
asyncCache: lila.memo.AsyncCache2.Builder,
createdTtl: FiniteDuration,
rankingTtl: FiniteDuration)(implicit system: akka.actor.ActorSystem) {
@ -18,13 +19,13 @@ private[tournament] final class Cached(
def name(id: String): Option[String] = nameCache sync id
val promotable = AsyncCache.single(
val promotable = asyncCache.single(
name = "tournament.promotable",
TournamentRepo.promotable,
timeToLive = createdTtl)
expireAfter = _.ExpireAfterWrite(createdTtl))
def findNext(tour: Tournament): Fu[Option[Tournament]] = tour.perfType ?? { pt =>
promotable(true) map { tours =>
promotable.get map { tours =>
tours
.filter(_.perfType contains pt)
.filter(_.isScheduled)
@ -34,18 +35,18 @@ private[tournament] final class Cached(
}
def ranking(tour: Tournament): Fu[Ranking] =
if (tour.isFinished) finishedRanking(tour.id)
else ongoingRanking(tour.id)
if (tour.isFinished) finishedRanking get tour.id
else ongoingRanking get tour.id
// only applies to ongoing tournaments
private val ongoingRanking = AsyncCache[String, Ranking](
private val ongoingRanking = asyncCache.multi[String, Ranking](
name = "tournament.ongoingRanking",
f = PlayerRepo.computeRanking,
timeToLive = 3.seconds)
expireAfter = _.ExpireAfterWrite(3.seconds))
// only applies to finished tournaments
private val finishedRanking = AsyncCache[String, Ranking](
private val finishedRanking = asyncCache.multi[String, Ranking](
name = "tournament.finishedRanking",
f = PlayerRepo.computeRanking,
timeToLive = rankingTtl)
expireAfter = _.ExpireAfterAccess(rankingTtl))
}

View File

@ -17,6 +17,7 @@ final class Env(
system: ActorSystem,
db: lila.db.Env,
mongoCache: lila.memo.MongoCache.Builder,
asyncCache: lila.memo.AsyncCache2.Builder,
flood: lila.security.Flood,
hub: lila.hub.Env,
roundMap: ActorRef,
@ -55,6 +56,7 @@ final class Env(
lazy val forms = new DataForm
lazy val cached = new Cached(
asyncCache = asyncCache,
createdTtl = CreatedCacheTtl,
rankingTtl = RankingCacheTtl)(system)
@ -86,6 +88,7 @@ final class Env(
verify = verify,
indexLeaderboard = leaderboardIndexer.indexOne _,
roundMap = roundMap,
asyncCache = asyncCache,
standingChannel = standingChannel)
lazy val crudApi = new crud.CrudApi
@ -182,6 +185,7 @@ object Env {
system = lila.common.PlayApp.system,
db = lila.db.Env.current,
mongoCache = lila.memo.Env.current.mongoCache,
asyncCache = lila.memo.Env.current.asyncCache,
flood = lila.security.Env.current.flood,
hub = lila.hub.Env.current,
roundMap = lila.round.Env.current.roundMap,

View File

@ -35,6 +35,7 @@ final class TournamentApi(
trophyApi: lila.user.TrophyApi,
verify: Condition.Verify,
indexLeaderboard: Tournament => Funit,
asyncCache: lila.memo.AsyncCache2.Builder,
standingChannel: ActorRef) {
def createTournament(setup: TournamentSetup, me: User): Fu[Tournament] = {
@ -315,15 +316,15 @@ final class TournamentApi(
}
}
private val miniStandingCache = lila.memo.AsyncCache[String, List[RankedPlayer]](
private val miniStandingCache = asyncCache.multi[String, List[RankedPlayer]](
name = "tournament.miniStanding",
id => PlayerRepo.bestByTourWithRank(id, 30),
timeToLive = 3 second)
expireAfter = _.ExpireAfterWrite(3 second))
def miniStanding(tourId: String, withStanding: Boolean): Fu[Option[MiniStanding]] =
TournamentRepo byId tourId flatMap {
_ ?? { tour =>
if (withStanding) miniStandingCache(tour.id) map { rps =>
if (withStanding) miniStandingCache get tour.id map { rps =>
MiniStanding(tour, rps.some).some
}
else fuccess(MiniStanding(tour, none).some)

View File

@ -7,15 +7,15 @@ import reactivemongo.bson._
import lila.common.LightUser
import lila.db.dsl._
import lila.memo.{ ExpireSetMemo, MongoCache }
import lila.rating.{ Perf, PerfType }
import User.{ LightPerf, LightCount }
final class Cached(
userColl: Coll,
nbTtl: FiniteDuration,
onlineUserIdMemo: ExpireSetMemo,
mongoCache: MongoCache.Builder,
onlineUserIdMemo: lila.memo.ExpireSetMemo,
mongoCache: lila.memo.MongoCache.Builder,
asyncCache: lila.memo.AsyncCache2.Builder,
rankingApi: RankingApi) {
private def oneWeekAgo = DateTime.now minusWeeks 1
@ -77,10 +77,10 @@ final class Cached(
timeToLive = 34 minutes,
keyToString = _.toString)
val top50Online = lila.memo.AsyncCache.single[List[User]](
val top50Online = asyncCache.single[List[User]](
name = "user.top50online",
f = UserRepo.byIdsSortRating(onlineUserIdMemo.keys, 50),
timeToLive = 10 seconds)
expireAfter = _.ExpireAfterWrite(10 seconds))
object ranking {

View File

@ -4,12 +4,12 @@ import akka.actor._
import com.typesafe.config.Config
import lila.common.PimpedConfig._
import lila.memo.{ ExpireSetMemo, MongoCache }
final class Env(
config: Config,
db: lila.db.Env,
mongoCache: MongoCache.Builder,
mongoCache: lila.memo.MongoCache.Builder,
asyncCache: lila.memo.AsyncCache2.Builder,
scheduler: lila.common.Scheduler,
timeline: ActorSelection,
system: ActorSystem) {
@ -29,13 +29,13 @@ final class Env(
lazy val lightUserApi = new LightUserApi(userColl)(system)
lazy val onlineUserIdMemo = new ExpireSetMemo(ttl = OnlineTtl)
lazy val onlineUserIdMemo = new lila.memo.ExpireSetMemo(ttl = OnlineTtl)
lazy val noteApi = new NoteApi(db(CollectionNote), timeline, system.lilaBus)
lazy val trophyApi = new TrophyApi(db(CollectionTrophy))
lazy val rankingApi = new RankingApi(db(CollectionRanking), mongoCache, lightUser)
lazy val rankingApi = new RankingApi(db(CollectionRanking), mongoCache, asyncCache, lightUser)
lazy val jsonView = new JsonView(isOnline)
@ -80,6 +80,7 @@ final class Env(
nbTtl = CachedNbTtl,
onlineUserIdMemo = onlineUserIdMemo,
mongoCache = mongoCache,
asyncCache = asyncCache,
rankingApi = rankingApi)
}
@ -89,6 +90,7 @@ object Env {
config = lila.common.PlayApp loadConfig "user",
db = lila.db.Env.current,
mongoCache = lila.memo.Env.current.mongoCache,
asyncCache = lila.memo.Env.current.asyncCache,
scheduler = lila.common.PlayApp.scheduler,
timeline = lila.hub.Env.current.actor.timeline,
system = lila.common.PlayApp.system)

View File

@ -7,12 +7,12 @@ import reactivemongo.bson._
import scala.concurrent.duration._
import lila.db.dsl._
import lila.memo.{ AsyncCache, MongoCache }
import lila.rating.{ Perf, PerfType }
final class RankingApi(
coll: Coll,
mongoCache: MongoCache.Builder,
mongoCache: lila.memo.MongoCache.Builder,
asyncCache: lila.memo.AsyncCache2.Builder,
lightUser: lila.common.LightUser.Getter) {
import RankingApi._
@ -72,13 +72,13 @@ final class RankingApi(
def of(userId: User.ID): Fu[Map[Perf.Key, Int]] =
lila.common.Future.traverseSequentially(PerfType.leaderboardable) { perf =>
cache(perf.id) map { _ get userId map (perf.key -> _) }
cache.get(perf.id) map { _ get userId map (perf.key -> _) }
} map (_.flatten.toMap)
private val cache = AsyncCache[Perf.ID, Map[User.ID, Rank]](
private val cache = asyncCache.multi[Perf.ID, Map[User.ID, Rank]](
name = "rankingApi.weeklyStableRanking",
f = compute,
timeToLive = 15 minutes,
expireAfter = _.ExpireAfterWrite(15 minutes),
resultTimeout = 10 seconds)
private def compute(perfId: Perf.ID): Fu[Map[User.ID, Rank]] =