The purpose here is to implement a very simple cache for an actor that needs to call an external service (or some expensive but highly cacheable operation) without using mutable state.
class A extends Actor{
def receive = {
case GetCommand =>
val response = callExternalService()
context.become(receiveWithCache(response))
context.system.scheduler.schedule(1 day, 1 day, self, InvalidateCache)
sender ! response
}
def receiveWithCache(cachedResponse:R): PartialFunction[Any,Unit] = {
case GetCommand => sender ! cachedResponse
case InvalidateCache => context.unbecome
}
}
I know there are more advanced ways to implement this, among which a fully fledged CacheSystem that can be found in the Akka patterns pages, but in some cases that really isn't required.
Plus, it's interesting to know the answer if using become like this is safe.
Actors are 'Treadsafe'. The Actor System (AKKA), provides each actor with its own 'light-weight thread'. Meaning that this is not a tread, but the AKKA system will give the impression that an Actor is always running in it's own thread to the developer.
Akka is an open source, event-driven middleware project. It is designed to allow developers to write simpler, correct concurrent applications using Actors, STM and transactors. Akka is an open source, event-driven middleware project.
No, using the ? does not block the current thread. It returns a Future immediately.
Akka Persistence enables stateful actors to persist their state so that it can be recovered when an actor is either restarted, such as after a JVM crash, by a supervisor or a manual stop-start, or migrated within a cluster.
As far as I know this technique is sound and should be good for you to use. It's actually a more clever way to get around having to have a mutable var response
in your code. I actully used this technique in an answer here and Viktor from the Akka team seemed to think it was a good solution. One thing though, you can change:
def receiveWithCache(cachedResponse:R): PartialFunction[Any,Unit] = {
case GetCommand => sender ! cachedResponse
case InvalidateCache => context.unbecome
}
to:
def receiveWithCache(cachedResponse:R): Receive = {
case GetCommand => sender ! cachedResponse
case InvalidateCache => context.unbecome
}
The Receive
type is a shorthand alias for PartialFunction[Any,Unit]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With