67 lines
2.1 KiB
Scala
67 lines
2.1 KiB
Scala
package lila.hub
|
|
|
|
import com.github.benmanes.caffeine.cache._
|
|
import java.util.concurrent.TimeUnit
|
|
import ornicar.scalalib.Zero
|
|
import play.api.Mode
|
|
import scala.concurrent.duration.FiniteDuration
|
|
import scala.concurrent.Promise
|
|
import scala.jdk.CollectionConverters._
|
|
|
|
final class SyncActorMap[T <: SyncActor](
|
|
mkActor: String => T,
|
|
accessTimeout: FiniteDuration
|
|
)(implicit mode: Mode) {
|
|
|
|
def getOrMake(id: String): T = actors get id
|
|
|
|
def getIfPresent(id: String): Option[T] = Option(actors getIfPresent id)
|
|
|
|
def tell(id: String, msg: Any): Unit = getOrMake(id) ! msg
|
|
|
|
def tellIfPresent(id: String, msg: => Any): Unit = getIfPresent(id) foreach (_ ! msg)
|
|
|
|
def tellAll(msg: Any) = actors.asMap.asScala.foreach(_._2 ! msg)
|
|
|
|
def tellIds(ids: Seq[String], msg: Any): Unit = ids foreach { tell(_, msg) }
|
|
|
|
def ask[A](id: String)(makeMsg: Promise[A] => Any): Fu[A] = getOrMake(id).ask(makeMsg)
|
|
|
|
def askIfPresent[A](id: String)(makeMsg: Promise[A] => Any): Fu[Option[A]] =
|
|
getIfPresent(id) ?? {
|
|
_ ask makeMsg dmap some
|
|
}
|
|
|
|
def askIfPresentOrZero[A: Zero](id: String)(makeMsg: Promise[A] => Any): Fu[A] =
|
|
askIfPresent(id)(makeMsg) dmap (~_)
|
|
|
|
def exists(id: String): Boolean = actors.getIfPresent(id) != null
|
|
|
|
def size: Int = actors.estimatedSize().toInt
|
|
|
|
def kill(id: String): Unit = actors invalidate id
|
|
|
|
def killAll(): Unit = actors.invalidateAll()
|
|
|
|
def touch(id: String): Unit = actors.getIfPresent(id).unit
|
|
|
|
def touchOrMake(id: String): Unit = actors.get(id).unit
|
|
|
|
private[this] val actors: LoadingCache[String, T] =
|
|
lila.common.LilaCache
|
|
.caffeine(mode)
|
|
.recordStats
|
|
.expireAfterAccess(accessTimeout.toMillis, TimeUnit.MILLISECONDS)
|
|
.removalListener(new RemovalListener[String, T] {
|
|
def onRemoval(id: String, actor: T, cause: RemovalCause): Unit =
|
|
actor.stop()
|
|
})
|
|
.build[String, T](new CacheLoader[String, T] {
|
|
def load(id: String): T = mkActor(id)
|
|
})
|
|
|
|
def monitor(name: String) = lila.mon.caffeineStats(actors, name)
|
|
|
|
def keys: Set[String] = actors.asMap.asScala.keySet.toSet
|
|
}
|