Creating a lazy actor router in Akka with timeout - akka

I have spent the last two days learning Actors, and I want to create an expiring cache. Now we use a tenant model so I want each tenant to be represented by an actor. I would like these actors to be created when required, and timeout after a period of being idle.
To solve this I have mocked up the following as I am unaware of a provided solution, and am looking for any critique or validation of the approach.
//A simple Message carrying just the name of the actor
case class Message(name:String)
//Actor that will expire after a timeout period and stop itself
class ExpireActor extends Actor {
val id = Random.nextInt(1000)
context.setReceiveTimeout(100 milliseconds)
def receive ={
case Message(_) => println("Message: " + id + " " + System.currentTimeMillis())
case ReceiveTimeout => {
println("Timeout: " + id + " " + System.currentTimeMillis())
self ! PoisonPill
}
}
}
//Router for creating actors on demand
case class LazyRouter() extends RouterConfig {
def routerDispatcher: String = Dispatchers.DefaultDispatcherId
def supervisorStrategy: SupervisorStrategy = SupervisorStrategy.defaultStrategy
def createRoute(routeeProvider: RouteeProvider): Route = {
{
case (sender, Message(name)) ⇒
routeeProvider.context
.child(name)
.map(a => List(Destination(sender, a)))
.getOrElse{
synchronized {
routeeProvider.context
.child(name) //Dont want to call sync until I have to, so need to check existence again
.map(a => List(Destination(sender, a)))
.getOrElse{
val ref = routeeProvider.context.actorOf(Props[ExpireActor], name)
routeeProvider.registerRoutees(List(ref))
List(Destination(sender, ref))
}
}
}
}
}
}

I'm not sure I'm fully on board with your approach. Actors are very lightweight. When they are not doing anything they are not costing you anything CPU wise. Why not just pre-create all of the cache actors (for each possible tenant) before hand so the router does not have to have that scary synchronized block around whether or not it needs to create the routee. Then, instead of stopping the actors when they are idle for a specific amount of time, just clear out their internal state (which I'm assuming is the cached data) if you want to free up that memory. This will greatly simplify your code and make it more reliable (and probably faster to boot).

Related

how to avoid sending messages to actors not created yet?

I hope it is ok to ask this. I am using akka and have two actors, where one is initiated/created fast and the other much slower. The rapidly created one asks the other for something (ask-pattern), and the message is sent to dead letters since the other is not initiated yet. What is the preferred way of making an actor waiting with sending it´s message? I am not so eager to make an actor sleep or something without knowing there is no other way.
I would use the functionality become()/unbecome() Akka provides for Actors. I am assuming in the following code that the slowActor gets created by the fastActor. The trick here is that the fastActor will have two behaviors: one for when the slowActor is getting initiated and the other for when it's ready to do some work. When slowActor is ready, it will send a message to the fastActor to advertise that is able to receive messages. fastActor will be watching slowActor and if it gets terminated, it will change its behavior again. What to do next would be up to your solution.
Here is a mock code as a guide (I have not compiled the code and it might contain some errors):
case object Ready
case object DoWork
case object WorkDone
class FastActor extends Actor with ActorLogging {
val slowActor = context.actorOf(SlowActor.props)
context.watch(slowActor)
def receive = slowActorNotReadyBehavior
def slowActorNotReadyBehavior = {
case DoWork => log.warning("Slow actor in not ready, I am sorry...")
case Ready => context.become(slowActorReadyBehavior)
}
def slowActorReadyBehavior = {
case DoWork => (slowActor ? DoWork).pipeTo(self)
case Terminated(ref) =>
log.error("Slow actor terminated")
context.unbecome()
//... do something with slowActor
}
}
class SlowActor extends Actor {
override def preStart = {
context.parent ! Ready
}
def receive = {
case DoWork =>
//do something
sender ! WorkDone
}
}

Waiting for multiple results in Akka

What is the proper way to wait for the result of multiple actors in Akka?
The Principles of Reactive Programming Coursera course had an exercise with a replicated key-value store. Without going into the details of the assignment, it required waiting on the acknowledgement of multiple actors before it could indicate the replication was complete.
I implemented the assignment using a mutable map containing the outstanding requests, but I felt the solution had a 'bad smell'. I hoped there was a better way to implement what seems like a common scenario.
In an attempt to uphold the classes' honor code by withholding my solution to the exercise, I have an abstract use case that describes a similar problem.
An invoice line item needs to calculate its tax liability. The tax liability is combination of all the taxes applied to the line item across multiple taxing authorities (e.g., federal, state, police district). If each taxing authority was an actor capable of determining the tax liability of the line item, the line item would need all actors to report before it could continue report the overall tax liability. What is the best/right way to accomplish this scenario in Akka?
Here is a simplified example of what I believe you are looking for. It shows how a master like actor spawns some child workers and then waits for all of their responses, handling the situation where a timeout can occur waiting for results. The solution shows how to wait for an initial request and then switch over to a new receive function when waiting for the responses. It also shows how to propagate state into the waiting receive function to avoid having to have explicit mutable state at the instance level.
object TaxCalculator {
sealed trait TaxType
case object StateTax extends TaxType
case object FederalTax extends TaxType
case object PoliceDistrictTax extends TaxType
val AllTaxTypes:Set[TaxType] = Set(StateTax, FederalTax, PoliceDistrictTax)
case class GetTaxAmount(grossEarnings:Double)
case class TaxResult(taxType:TaxType, amount:Double)
case class TotalTaxResult(taxAmount:Double)
case object TaxCalculationTimeout
}
class TaxCalculator extends Actor{
import TaxCalculator._
import context._
import concurrent.duration._
def receive = waitingForRequest
def waitingForRequest:Receive = {
case gta:GetTaxAmount =>
val children = AllTaxTypes map (tt => actorOf(propsFor(tt)))
children foreach (_ ! gta)
setReceiveTimeout(2 seconds)
become(waitingForResponses(sender, AllTaxTypes))
}
def waitingForResponses(respondTo:ActorRef, expectedTypes:Set[TaxType], taxes:Map[TaxType, Double] = Map.empty):Receive = {
case TaxResult(tt, amount) =>
val newTaxes = taxes ++ Map(tt -> amount)
if (newTaxes.keySet == expectedTypes){
respondTo ! TotalTaxResult(newTaxes.values.foldLeft(0.0)(_+_))
context stop self
}
else{
become(waitingForResponses(respondTo, expectedTypes, newTaxes))
}
case ReceiveTimeout =>
respondTo ! TaxCalculationTimeout
context stop self
}
def propsFor(taxType:TaxType) = taxType match{
case StateTax => Props[StateTaxCalculator]
case FederalTax => Props[FederalTaxCalculator]
case PoliceDistrictTax => Props[PoliceDistrictTaxCalculator]
}
}
trait TaxCalculatingActor extends Actor{
import TaxCalculator._
val taxType:TaxType
val percentage:Double
def receive = {
case GetTaxAmount(earnings) =>
val tax = earnings * percentage
sender ! TaxResult(taxType, tax)
}
}
class FederalTaxCalculator extends TaxCalculatingActor{
val taxType = TaxCalculator.FederalTax
val percentage = 0.20
}
class StateTaxCalculator extends TaxCalculatingActor{
val taxType = TaxCalculator.StateTax
val percentage = 0.10
}
class PoliceDistrictTaxCalculator extends TaxCalculatingActor{
val taxType = TaxCalculator.PoliceDistrictTax
val percentage = 0.05
}
Then you could test this out with the following code:
import TaxCalculator._
import akka.pattern.ask
import concurrent.duration._
implicit val timeout = Timeout(5 seconds)
val system = ActorSystem("taxes")
import system._
val cal = system.actorOf(Props[TaxCalculator])
val fut = cal ? GetTaxAmount(1000.00)
fut onComplete{
case util.Success(TotalTaxResult(amount)) =>
println(s"Got tax total of $amount")
case util.Success(TaxCalculationTimeout) =>
println("Got timeout calculating tax")
case util.Failure(ex) =>
println(s"Got exception calculating tax: ${ex.getMessage}")
}
This is a very common problem in Akka. You have multiple actors that will do the job for you and you need to combine them.
Solution proposed by Jammie Allen in his book "Effective Akka" (it was about getting bank account balance from various types of accounts) is that you spawn an actor that will spawn multiple actors that will do the job (e.g. calculate you tax). And it will wait for all of them to answer.
One catch that you should not use ask but insted tell.
When you spaw your multiple actors (e.g. FederalTaxactor, StateTaxActor...) you send them a message with the data they need to process. Then you know how many answers you need to collect. With every response you check if all responses are there. If not you wait.
The problem is that you might wait forever if any of the actors fail. So you schedule a timeout message to yourself. If not all answers are there you return that the operation did not complete successfully.
Akka has a special utility for scheduling a timeout to yourself available as a nice helper.
As prior answer have suggested, you may find the ability to compose futures helpful in this case - the best description of Futures (and Promises, which are somewhat related) I know of is here: http://docs.scala-lang.org/overviews/core/futures.html
This may help explain the ways composable futures could answer the need, perhaps more cleanly than actors, or in combination with actors.
my experience with streams in this case work fine.
I start a Source with the ActorRefs, then send msg with ask through mapAsync to ActorRefs and collect the responses to Seq.
val f = Source(workers)
.mapAsync(USED_THREAD_COUNT)
(actorRef => (actorRef ? QueryState).mapTo[StateResponse]))
.runWith(Sink.seq)
f onComplete { responses =>
// validate and work with responses
}
I hope it will help you.

Binding AKKA actors to context

Is it possible to bind a set of AKKA actors to a certain context?
E.g. I have three actors and each of them are implementing a state machine. These actors send messages to each other on certain state transitions. Now I want to bind these state to a context, e.g. a user context. So I have a user (represented by an userId) who has a set of actors bound in certain states. As long as this user context exists these actors (or at least their states) must be bound to the user's context. Is this possible per se in AKKA or do I have to persist the state of the different actors user-wise? Or are actors not designed for these use cases?
I'm not 100% sure that I get what you are asking, but I'll take a shot at an answer anyway. The actor system itself is heirarchical. Parent/child relationships exist in the heirarchy and the parent will be the owner (and supervisor) to the children. If you modeled your system with a UserContext actor being the parent to three child actors (your FSM actors) then I suppose the children will be bound to this UserContext actor instance. Consider this simplified example model:
class UserContext extends Actor{
val stateA = context.actorOf(Props[StateA])
val stateB = context.actorOf(Props[StateB])
val stateC = context.actorOf(Props[StateC])
def receive = {
case _ =>
}
}
class StateA extends Actor{
def receive = {
case _ =>
}
}
class StateB extends Actor{
def receive = {
case _ =>
}
}
class StateC extends Actor{
def receive = {
case _ =>
}
}
If you set things up this way, the state children will be started up when this user context instance is created and will also be stopped when the user context instance is stopped. Now all you need is a little code to make sure only one user context per user exists in the system. You could do something like this to assure that:
object UserContext{
def apply(username:String)(implicit system:ActorSystem):ActorRef = {
val ctx = system.actorFor("/user/" + username)
if (ctx.isTerminated){
try{
system.actorOf(Props[UserContext], username)
}
catch{
case InvalidActorNameException(msg) if msg.contains("unique") => apply(username)
}
}
else
ctx
}
}
This factory object makes sure the user context actor for the supplied username is not currently running. If it is, it just returns that ref. If not, it starts it up and binds it to the name of the user for later lookups.
Once you do things like this, just use the factory to lookup the UserContext for a supplied username and then route all messages through it and let it delegate messages to the correct child state actor. This is obviously quite simplified, but I think it might be something similar to what you want.

Akka 2.1 Remote: sharing actor across systems

I'm learnin about remote actors in Akka 2.1 and I tried to adapt the counter example provided by Typesafe.
I implemented a quick'n'dirty UI from the console to send ticks. And to quit with asking(and showing the result) the current count.
The idea is to start a master node that will run the Counter actor and some client node that will send messages to it through remoting. However I'd like to achieve this through configuration and minimal changes to code. So by changing the configuration local actors could be used.
I found this blog entry about similar problem where it was necessary that all API calls go through one actor even though there are many instances running.
I wrote similar configuration but I cant get it to work. My current code does use remoting but it creates a new actor on the master for each new node and I can't get it to connect to existing actor without explicitly giving it the path(and defying the point of configuration). However this is not what I want since state cannot be shared between JVMs this way.
Full runnable code available through a git repo
This is my config file
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/counter {
remote = "akka://ticker#127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
And full source
import akka.actor._
import akka.pattern.ask
import scala.concurrent.duration._
import akka.util.Timeout
import scala.util._
case object Tick
case object Get
class Counter extends Actor {
var count = 0
val id = math.random.toString.substring(2)
println(s"\nmy name is $id\ni'm at ${self.path}\n")
def log(s: String) = println(s"$id: $s")
def receive = {
case Tick =>
count += 1
log(s"got a tick, now at $count")
case Get =>
sender ! count
log(s"asked for count, replied with $count")
}
}
object AkkaProjectInScala extends App {
val system = ActorSystem("ticker")
implicit val ec = system.dispatcher
val counter = system.actorOf(Props[Counter], "counter")
def step {
print("tick or quit? ")
readLine() match {
case "tick" => counter ! Tick
case "quit" => return
case _ =>
}
step
}
step
implicit val timeout = Timeout(5.seconds)
val f = counter ? Get
f onComplete {
case Failure(e) => throw e
case Success(count) => println("Count is " + count)
}
system.shutdown()
}
I used sbt run and in another window sbt run -Dakka.remote.netty.port=0 to run it.
I found out I can use some sort of pattern. Akka remote allows only for deploying on remote systems(can't find a way to make it look up on remote just through configuration..am I mistaken here?).
So I can deploy a "scout" that will pass back the ActorRef. Runnable code available on the original repo under branch "scout-hack". Because this feels like a hack. I will still appreciate configuration based solution.
The actor
case object Fetch
class Scout extends Actor{
def receive = {
case Fetch => sender ! AkkaProjectInScala._counter
}
}
Counter actor creating is now lazy
lazy val _counter = system.actorOf(Props[Counter], "counter")
So it only executes on the master(determined by the port) and can be fetched like this
val counter: ActorRef = {
val scout = system.actorOf(Props[Scout], "scout")
val ref = Await.result(scout ? Fetch, timeout.duration) match {
case r: ActorRef => r
}
scout ! PoisonPill
ref
}
And full config
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/scout {
remote = "akka://ticker#127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
EDIT: I also found a clean-ish way: check configuration for "counterPath" anf if present actorFor(path) else create actor. Nice and you can inject the master when running and code is much cleaner than with the "scout" but it still has to decide weather to look up or create an actor. I guess this cannot be avoided.
I tried your git project and it actually works fine, aside from a compilation error, and that you must start the sbt session with -Dakka.remote.netty.port=0 parameter to the jvm, not as parameter to run.
You should also understand that you don't have to start the Counter actor in both processes. In this example it's intended to be created from the client and deployed on the server (port 2552). You don't have to start it on the server. It should be enough to create the actor system on the server for this example.

Unit testing scala actors

Anyone know of a good way to unit test Scala actors? In the general sense I have an actor that receives a message and will send out other messages in response. This is done on multiple threads, and an actor that is not correct may either send the wrong messages or no message at all. I need a simple way of creating a mockup actor that send and receives messages to the actor being tested. Any experiences in this area?
Because of the dynamic nature of actor-style message passing, mocking actors is usually no trouble at all. Just create an actor which receives the desired message and you're home free. You will of course need to ensure that this mock actor is the one to which messages are passed, but that shouldn't be a problem as long as the actor you are attempting to test is reentrant.
I think the complexity depends on a couple factors...
How stateful is the actor?
If it behaves like a idempotent function, only asynchronous, then it should be a simple matter of mocking up an actor that sends a message and then checks that it receives the expected messages back. You probably want to use a react/receiveWithin on the mock actor in case there is response within a reasonable period of time you can fail rather than hanging.
However if the messages aren't independent of one another, then you should test it with various sequences of messages and expected results.
How many actors will the actor being tested interact with?
If an actor is expected to interact with many others, and it is stateful, then it should be tested with several actors sending/receiving messages. Since you probably have no guarantee of the order in which the messages will arrive, you should be sure to either permute the orders in which the actors send the messages or introduce random pauses in the actors generating messages and run the test many times.
I'm not aware of any prebuilt frameworks for testing actors, but you could possibly look to Erlang for inspiration.
http://svn.process-one.net/contribs/trunk/eunit/doc/overview-summary.html
I have been wondering about how to test Actors myself.
Here is what I came up with, does anybody see problems with this approach?
Rather than send messages directly, what if your actor delegated message sending to a function?
Then your tests can swap out the function with one that tracks the number of times called and/or the arguments with which the method was called:
class MyActor extends Actor {
var sendMessage:(Actor, ContactMsg) => Unit = {
(contactActor, msg) => {
Log.trace("real sendMessage called")
contactActor ! msg
}
}
var reactImpl:PartialFunction(Any, Unit) = {
case INCOMING(otherActor1, otherActor2, args) => {
/* logic to test */
if(args){
sendMessage(otherActor1, OUTGOING_1("foo"))
} else {
sendMessage(otherActor2, OUTGOING_2("bar"))
}
}
}
final def act = loop {
react {
reactImpl
}
}
Your test case might contain code like:
// setup the test
var myActor = new MyActor
var target1 = new MyActor
var target2 = new MyActor
var sendMessageCalls:List[(Actor, String)] = Nil
/*
* Create a fake implementation of sendMessage
* that tracks the arguments it was called with
* in the sendMessageCalls list:
*/
myActor.sendMessage = (actor, message) => {
Log.trace("fake sendMessage called")
message match {
case OUTGOING_1(payload) => {
sendMessageCalls = (actor, payload) :: sendMessageCalls
}
case _ => { fail("Unexpected Message sent:"+message) }
}
}
// run the test
myActor.start
myActor.reactImpl(Incoming(target1, target2, true))
// assert the results
assertEquals(1, sendMessageCalls.size)
val(sentActor, sentPayload) = sendMessageCalls(0)
assertSame(target1, sentActor)
assertEquals("foo", sentPayload)
// .. etc.
My attempt at unit testing an actor (it works). I'm using Specs as a framework.
object ControllerSpec extends Specification {
"ChatController" should{
"add a listener and respond SendFriends" in{
var res = false
val a = actor{}
val mos = {ChatController !? AddListener(a)}
mos match{
case SendFriends => res = true
case _ => res = false
}
res must beTrue
}
How this works is by sending a synchronous call to the singleton ChatController. ChatController responds by use of reply(). The response is sent as a return of the called function, which gets stored into mos. Then a match is applied to mos getting the case class that was sent from ChatController. If the result is what is expected (SendFriends) set res to true. The res must beTrue assertion determines the success or failure of test.
My actor singleton that I'm testing
import ldc.socialirc.model._
import scala.collection.mutable.{HashMap, HashSet}
import scala.actors.Actor
import scala.actors.Actor._
import net.liftweb.util.Helpers._
//Message types
case class AddListener(listener: Actor)
case class RemoveListener(listener: Actor)
case class SendFriends
//Data Types
case class Authority(usr: Actor, role: String)
case class Channel(channelName: String, password: String, creator: String, motd: String, users: HashSet[Authority])
object ChatController extends Actor {
// The Channel List - Shows what actors are in each Chan
val chanList = new HashMap[String, Channel]
// The Actor List - Shows what channels its in
val actorList = new HashMap[Actor, HashSet[String]]
def notifyListeners = {
}
def act = {
loop {
react {
case AddListener(listener: Actor)=>
actorList += listener -> new HashSet[String]
reply(SendFriends)
}
}
}
start //Dont forget to start
}
Though its not complete it does return the Sendfriends case class as expected.
Suite for unit testing of Actors has recently been added to Akka. You can find some information and code snippets in this blogpost.