Skip to content

Instantly share code, notes, and snippets.

@lregnier
Created April 27, 2018 15:56
Show Gist options
  • Save lregnier/e271d29a0039b6bccb03e943bde83f14 to your computer and use it in GitHub Desktop.
Save lregnier/e271d29a0039b6bccb03e943bde83f14 to your computer and use it in GitHub Desktop.
Akka's ActorCaching
import akka.actor.{Actor, ActorLogging, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider}
import akka.pattern.pipe
import com.typesafe.config.Config
import scala.concurrent.Future
import scala.concurrent.duration.Duration
object ActorCaching {
case class SaveToCache(msg: Any, response: Any)
case class RemoveFromCache(msg: Any)
}
trait ActorCaching { this: Actor with ActorLogging =>
import ActorCaching._
import context.dispatcher
private val cache = ActorCache()
private val cacheSettings = ActorCacheSettings(context.system)
override def receive: Receive = {
case SaveToCache(msg, response) =>
cache.put(msg, response)
context.system.scheduler.scheduleOnce(cacheSettings.defaultTll, self, RemoveFromCache(msg))
case RemoveFromCache(msg) =>
cache.remove(msg)
case msg if cache.contains(msg) =>
sender ! cache.get(msg)
case msg if cachedReceive.isDefinedAt(msg) =>
cachedReceive(msg)
}
def respond[A](msg: Any, response: Future[A], cache: Boolean = true): Unit = {
if (cache) response.foreach(r => self ! SaveToCache(msg, r))
response pipeTo sender()
}
def cachedReceive: Receive
}
// ActorCache
class ActorCache {
private var cache: Map[Any, Any] = Map()
def put(msg: Any, response: Any): Unit = cache = cache + (msg -> response)
def get(msg: Any): Any = cache(msg)
def remove(msg: Any): Unit = cache = cache - msg
def contains(msg: Any): Boolean = cache.contains(msg)
}
object ActorCache {
def apply(): ActorCache = new ActorCache()
}
// Settings
class ActorCacheSettings(config: Config) extends Extension {
private val actorCacheConfig = config.getConfig("akka.actor.cache")
val defaultTll = Duration.fromNanos(actorCacheConfig.getDuration("default-ttl").toNanos)
}
object ActorCacheSettings extends ExtensionId[ActorCacheSettings] with ExtensionIdProvider {
override def createExtension(system: ExtendedActorSystem): ActorCacheSettings = new ActorCacheSettings(system.settings.config)
override def lookup(): ExtensionId[_ <: Extension] = ActorCacheSettings
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment