How can I gather state information from a set of actors using only the actorSystem? - scala

I'm creating an actor system, which has a list of actors representing some kind of session state.
These session are created by a factory actor (which might, in the future, get replaced by a router, if performance requires that - this should be transparent to the rest of the system, however).
Now I want to implement an operation where I get some state information from each of my currently existing session actors.
I have no explicit session list, as I want to rely on the actor system "owning" the sessions. I tried to use the actor system to look up the current session actors. The problem is that I did not find a "get all actor refs with this naming pattern" method. I tried to use the "/" operator on the system, followed by resolveOne - but got lost in a maze of future types.
The basic idea I had was:
- Send a message to all current session actors (as given to my by my ActorSystem).
- Wait for a response from them (preferably by using just the "ask" pattern - the method calling this broadcaster request/response is just a monitoring resp. debugging method, so blocking is no probleme here.
- And then collect the responses into a result.
After a death match against Scala's type system I had to give up for now.
Is there really no way of doing something like this?

If I understand the question correctly, then I can offer up a couple of ways you can accomplish this (though there are certainly others).
Option 1
In this approach, there will be an actor that is responsible for waking up periodically and sending a request to all session actors to get their current stats. That actor will use ActorSelection with a wildcard to accomplish that goal. A rough outline if the code for this approach is as follows:
case class SessionStats(foo:Int, bar:Int)
case object GetSessionStats
class SessionActor extends Actor{
def receive = {
case GetSessionStats =>
println(s"${self.path} received a request to get stats")
sender ! SessionStats(1, 2)
}
}
case object GatherStats
class SessionStatsGatherer extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
def receive = {
case GatherStats =>
println("Waking up to gether stats")
val sel = context.system.actorSelection("/user/session*")
sel ! GetSessionStats
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
Then you could test this code with the following:
val system = ActorSystem("test")
system.actorOf(Props[SessionActor], "session-1")
system.actorOf(Props[SessionActor], "session-2")
system.actorOf(Props[SessionStatsGatherer])
Thread.sleep(10000)
system.actorOf(Props[SessionActor], "session-3")
So with this approach, as long as we use a naming convention, we can use an actor selection with a wildcard to always find all of the session actors even though they are constantly coming (starting) and going (stopping).
Option 2
A somewhat similar approach, but in this one, we use a centralized actor to spawn the session actors and act as a supervisor to them. This central actor also contains the logic to periodically poll for stats, but since it's the parent, it does not need an ActorSelection and can instead just use its children list. That would look like this:
case object SpawnSession
class SessionsManager extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
var sessionCount = 1
def receive = {
case SpawnSession =>
val session = context.actorOf(Props[SessionActor], s"session-$sessionCount")
println(s"Spawned session: ${session.path}")
sessionCount += 1
sender ! session
case GatherStats =>
println("Waking up to get session stats")
context.children foreach (_ ! GetSessionStats)
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
And could be tested as follows:
val system = ActorSystem("test")
val manager = system.actorOf(Props[SessionsManager], "manager")
manager ! SpawnSession
manager ! SpawnSession
Thread.sleep(10000)
manager ! SpawnSession
Now, these examples are extremely trivialized, but hopefully they paint a picture for how you could go about solving this issue with either ActorSelection or a management/supervision dynamic. And a bonus is that ask is not needed in either and also no blocking.

There have been many additional changes in this project, so my answer/comments have been delayed quite a bit :-/
First, the session stats gathering should not be periodical, but on request. My original idea was to "mis-use" the actor system as my map of all existing session actors, so that I would not need a supervisor actor knowing all sessions.
This goal has shown to be elusive - session actors depend on shared state, so the session creator must watch sessions anyways.
This makes Option 2 the obvious answer here - the session creator has to watch all children anyways.
The most vexing hurdle with option 1 was "how to determine when all (current) answers are there" - I wanted the statistics request to take a snapshot of all currently existing actor names, query them, ignore failures (if a session dies before it can be queried, it can be ignored here) - the statistics request is only a debugging tool, i.e. something like a "best effort".
The actor selection api tangled me up in a thicket of futures (I am a Scala/Akka newbie), so I gave up on this route.
Option 2 is therefore better suited to my needs.

Related

Akka Classic Ask pattern. How does it match asks with responses?

I'm a newbie with Akka Actors, and I am learning about the Ask pattern. I am looking at the following example from alvin alexander:
class TestActor extends Actor {
def receive = {
case AskNameMessage => // respond to the "ask" request
sender ! "Fred"
case _ => println("that was unexpected")
}
}
...
val myActor = system.actorOf(Props[TestActor], name = "myActor")
// (1) this is one way to "ask" another actor
implicit val timeout = Timeout(5 seconds)
val future = myActor ? AskNameMessage
val result = Await.result(future, timeout.duration).asInstanceOf[String]
println(result)
(Yes, I know that Await.result isn't generally the best practice, but this is just a simple example.)
So from what I can tell, the only thing you need to do to implement the "askee" actor to service an Ask operation is to send a message back to the "asker" via the Tell operator, and that will be turned into a future on the "asker" side as a response to the Ask. Seems simple enough.
My question is this:
When the response comes back, how does Akka know that this particular message is the response to a certain Ask message?
In the example above, the "Fred" message doesn't contain any specific routing information that specifies that it's the response to a particular Ask operation. Does it just assume that the next message that the asker receives from that askee is the answer to the Ask? If that's the case, then what if one actor sends multiple Ask operations to the same askee? Wouldn't the responses likely get jumbled, causing random responses to be mapped to the wrong Asks?
Or, what if the asker is also receiving other types of messages from the same askee actor that are unrelated to these Ask messages? Couldn't the Asks receive response messages of the wrong type?
Just to be clear, I'm asking about Akka Classic, not Typed.
For every Ask message sent to an actor, akka creates a proxy ActorRef whose sole responsibility is to process one single message. This temp "actor" is initialized with a promise, which it needs to complete on message processing.
The source code of it is found here
but the main details are
private[akka] final class PromiseActorRef private (
val provider: ActorRefProvider,
val result: Promise[Any],
....
val alreadyCompleted = !result.tryComplete(promiseResult)
Now, it should be clear that Ask pattern is backed by independent unique actor asker for every message sent to the receiver askee.
The askee does know actor reference of the sender, or asker, of every message received via method context.sender(). Thus, it just needs to use this ActorRef to send a response back to the asker.
Finally, this all avoids any race conditions given that an actor only processes a message at a time. Thus it excludes any possibility of retrieving a "wrong" asker via method context.sender().

How does akka update a mutable state? [duplicate]

This question already has an answer here:
Does Akka onReceive method execute concurrently?
(1 answer)
Closed 1 year ago.
I read Akka documentation, but I do not understand:
class MyActor extends Actor {
private var _state = 0
override def receive: Receive = {
case x: Int =>
if (x != _state) {
println(s"---------> fail: ${x} and ${_state}")
}
_state = x + 1
}
}
implicit val system = ActorSystem("my-system")
val ref = system.actorOf(Props[MyActor], "my-actor")
(0 to 10000).foreach { x =>
ref ! x
}
I have a _state variable which is not #volatile and not atomic but at the same time _state is always correct, if I do changes with !-method.
How does Akka protect and update the internal state of actors?
Akka is an implementation of the Actor Model of computation. One of the (arguably the) key guarantees made by the actor model is that an actor only ever processes a single message at a time. Simply by virtue of having _state be private to an actor, you get a concurrency guarantee that's at least as strong as if you had every method of an object be #synchronized, with the added bonus of the ! operation to send a message being non-blocking.
Under the hood, a rough (simplified in a few places, but the broad strokes are accurate) outline of how it works and how the guarantee is enforced is:
Using the Props the ActorSystem constructs an instance of MyActor, places the only JVM reference to that instance inside an ActorCell (I'm told this terminology, as well as that the deep internals of Akka are "the dungeon", is inspired by the early development team for Akka being based in an office in what was previously a jail in Uppsala, Sweden), and keys that ActorCell with my-actor. In the meantime (technically this happens after system.actorOf has already returned the ActorRef), it constructs an ActorRef to allow user code to refer to the actor.
Inside the ActorCell, the receive method is called and the resulting PartialFunction[Any, Unit] (which has a type synonym of Receive) is saved in a field of the ActorCell which corresponds to the actor's behavior.
The ! operation on the ActorRef (at least for a local ActorRef) resolves which dispatcher is responsible for the actor and hands the message to the dispatcher. The dispatcher then enqueues the message into the mailbox of the ActorCell corresponding to my-actor (this is done in a thread-safe way).
If there is no task currently scheduled to process messages from the actor's mailbox, such a task is enqueued to the dispatcher's execution context to dequeue some (configurable) number of messages from the ActorCell's mailbox and process them, one-at-a-time, in a loop. After that loop, if there are more messages to process, another such task will be enqueued. Processing a message consists of passing it to the Receive stored in the ActorCell's behavior field (this mechanism allows the context.become pattern for changing behavior).
It's the last bit that provides the core of the guarantee that only one thread is ever invoking the Receive logic.
This is the Classic model for Akka Actors. If you are just learning actors then you should use Typed Actors because that is the supported model going forwards.
With typed actors, the actor system holds the state for each actor, not the actor itself. When an actor needs to process a message the actor system will pass the current state to the actor. The actor will return the new state back to the actor system when it has finished processing the message.
The typed model avoids all synchronisation issues because it does not use any external state, it only uses the state that is passed to it. And it does not modify any external state, it just returns a modified state value.
If you must use Classic actors then you can implement the same model using context.become rather than a var.

How to name an actor?

The data layer in my web application is comprised of Akka actors. Whenever I need to access data, I invoke the ActorSystem mechanism like so:
val myActor = system.actorOf(Props[MyActor], name = "myactor")
implicit val timeout = Timeout(120 seconds)
val future = myActor ? Request1
val result = Await.result(future, timeout.duration)
I'm using Play, and the ActorSystem variable is obtained through injection:
class MyClass #Inject() (system: ActorSystem)
But I'm getting the following exception saying that the actor name is not unique the second time I access the function, how to fix this? How to name the actor, taking into account that can be used concurrently by more than one thread?
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution
exception[[InvalidActorNameException: actor name [myactor] is not
unique!]]
** EDIT **
What I'm trying to achieve is something similar to having a container of Entity Beans in the EJB model, where each actor would be an Entity Bean. The difference I'm noticing is that the actors are not created/destroyed automatically as needed.
Depending on your goal, the question may be not how to name an actor, but when to create it. You are creating a new actor every time you need to access some data. I suppose you aren't stopping old actors when they are no longer needed.
You should probably create an actor once (or multiple times if you want a pool of actors, but using different names) and reuse it later by keeping an ActorRef somewhere or using dependency injected actors. You can also use system.actorFor or system.actorSelection (depending on Akka version you're using) if you really need to.
Most of the time you don't even need an explicit ActorRef because you want to reply to a sender of some message.
If you have to create a separate actor each time, then see Wonpyo's answer. In my opinion, though, you could simply use a Future directly instead.
There is a great guide on Actors in the Akka documentation.
Edit:
Since you specified you want each actor to act like a DAO class, I think it should look something like:
// Somewhere in some singleton object (injected as dependency)
val personDao : ActorRef = system.actorOf(Props[PersonDaoActor], name = "personDao")
val fruitDao : ActorRef = system.actorOf(Props[FruitDaoActor], name = "fruitDao")
Then, when you need to access some data:
val johnSmithFuture = personDao ? Get("John Smith")
johnSmithFuture.map {
case Person(name, age) => println(s"${name} ${age}")
}
Alternatively, instead of personDao you can use system.actorFor("personDao") (or system.actorSelection equivalent in Akka 2.4). You can also inject actors directly.
If you want multiple actors to process your messages in parallel you can use routers. Example:
val personDao: ActorRef =
system.actorOf(RoundRobinPool(5).props(Props[PersonDaoActor]), "personDao")
It would create 5 instances of your PersonDaoActor and distribute any messages sent to personDao among those 5 actors, so you could process 5 queries in parallel. If all 5 actors are busy, messages will be queued.
Using Await defeats the purpose of Akka in this case. There are some cases when this is the only option (legacy code, mostly), but using it every time effectively makes your code completely blocking, maybe even single-threaded (depending on your actor code). This is especially true in Play, which is designed to do everything asynchronously, so there's no need to Await.
It may be a good idea to reconsider if actors are really the best solution to your problem. If all you want is parallel execution, then Futures are much simpler. Some people still use actors in such case because they like the abstraction and the simplicity of routing. I found an interesting article describing this in detail: "Don't use Actors for concurrency" (also read the comments for opposing views).
Actor System requires unique name (path) for each actor.
Path has follwing format akka://system#host:port/user/{your-actor-path}
For example
val system = ActorSystem("hello")
val myActor = system.actorOf(Props[MyActor], name ="myactor")
// myActor Path
// "akka://hello/user/myactor" // purely local
// "akka.tcp://hello#ip:port/user/myactor" // remote
and in your code, myActor is created everytime, you make a call.
which makes an actor in the same path everytime.
Thus, Bad solution is to change the code as following
val myActor = system.actorOf(Props[MyActor])
If you don't assign a name to an actor then actor system will assign an random name
and myActor will not have same path for each function call.
But, this is really bad solution, since myActor will not be destructed
(Actor is not terminated by GC)
If you keep calling the function, then your memory will be out of space one day.
So, please DESTRUCT myActor after you done with the function.

Is Akka Ask Blocking on the Current Thread

I have a scenario where I have to fetch the details of a user by his id. It is a HTTP request that comes in and in my HTTP handler layer, I make use of the id that I get from the request, send a message to the actor which then talks to the database service to fetch the user.
Now since this is a HTTP request, I need to satisfy the request by sending a response back. So I thought of using the Akka ask pattern, but I have the following questions in mind:
Is this going to block on my current thread?
Is using ask pattern here to fetch a user in my case a scalable solution? I mean, I could have a few hundreds to a million users calling this end point at any given point in time. Is this a good idea to use the ask pattern to fetch a user?
In code, it looks like this in my HTTP controller
val result: Future[Any] = userActor ? FetchUser(id)
In my actor, I would do the following:
case fetchUser: FetchUser => sender ! myService.getUser(fetchUser.id)
Answering your questions in the same order you posed them:
No, using the ? does not block the current thread. It returns a Future immediately. However, the result within the Future may not be available immediately.
If you need the solution to be "scalable", and your service is capable of multiple concurrent queries, then you may need to use a pool of Actors so you can serve multiple ? at once, or see below for a Futures only, scalable, solution.
Futures Exclusively
If your Actors are not caching any intermediate values then you can just use Futures directly and avoid the rigmarole of Actors (e.g. Props, actorOf, receive, ?, ...):
import java.util.concurrent.Executors
import scala.concurrent.{ExecutionContext,Future}
object ServicePool {
private val myService = ???
val maxQueries = 11 //should come from a configuration file instead
private val queryExecutionPool =
ExecutionContext.fromExecutor(Executors.newFixedThreadPool(maxQueries))
type ID = ???
/**Will only hit the DB with maxQueries at once.*/
def queryService(id : ID) =
Future { myService getUser id }(queryExecutionPool)
}//end object ServiceQuery
You can now call ServicePool.queryService as often as you want but the service will not be hit with more than maxQueries at a single time, and no Actors:
val alotOfIDs : Seq[ID] = (1 to 1000000) map { i => ID(i)}
val results = alotOfIDs map ServicePool.queryService

Scala how to use akka actors to handle a timing out operation efficiently

I am currently evaluating javascript scripts using Rhino in a restful service. I wish for there to be an evaluation time out.
I have created a mock example actor (using scala 2.10 akka actors).
case class Evaluate(expression: String)
class RhinoActor extends Actor {
override def preStart() = { println("Start context'"); super.preStart()}
def receive = {
case Evaluate(expression) ⇒ {
Thread.sleep(100)
sender ! "complete"
}
}
override def postStop() = { println("Stop context'"); super.postStop()}
}
Now I run use this actor as follows:
def run {
val t = System.currentTimeMillis()
val system = ActorSystem("MySystem")
val actor = system.actorOf(Props[RhinoActor])
implicit val timeout = Timeout(50 milliseconds)
val future = (actor ? Evaluate("10 + 50")).mapTo[String]
val result = Try(Await.result(future, Duration.Inf))
println(System.currentTimeMillis() - t)
println(result)
actor ! PoisonPill
system.shutdown()
}
Is it wise to use the ActorSystem in a closure like this which may have simultaneous requests on it?
Should I make the ActorSystem global, and will that be ok in this context?
Is there a more appropriate alternative approach?
EDIT: I think I need to use futures directly, but I will need the preStart and postStop. Currently investigating.
EDIT: Seems you don't get those hooks with futures.
I'll try and answer some of your questions for you.
First, an ActorSystem is a very heavy weight construct. You should not create one per request that needs an actor. You should create one globally and then use that single instance to spawn your actors (and you won't need system.shutdown() anymore in run). I believe this covers your first two questions.
Your approach of using an actor to execute javascript here seems sound to me. But instead of spinning up an actor per request, you might want to pool a bunch of the RhinoActors behind a Router, with each instance having it's own rhino engine that will be setup during preStart. Doing this will eliminate per request rhino initialization costs, speeding up your js evaluations. Just make sure you size your pool appropriately. Also, you won't need to be sending PoisonPill messages per request if you adopt this approach.
You also might want to look into the non-blocking callbacks onComplete, onSuccess and onFailure as opposed to using the blocking Await. These callbacks also respect timeouts and are preferable to blocking for higher throughput. As long as whatever is way way upstream waiting for this response can handle the asynchronicity (i.e. an async capable web request), then I suggest going this route.
The last thing to keep in mind is that even though code will return to the caller after the timeout if the actor has yet to respond, the actor still goes on processing that message (performing the evaluation). It does not stop and move onto the next message just because a caller timed out. Just wanted to make that clear in case it wasn't.
EDIT
In response to your comment about stopping a long execution there are some things related to Akka to consider first. You can call stop the actor, send a Kill or a PosionPill, but none of these will stop if from processing the message that it's currently processing. They just prevent it from receiving new messages. In your case, with Rhino, if infinite script execution is a possibility, then I suggest handling this within Rhino itself. I would dig into the answers on this post (Stopping the Rhino Engine in middle of execution) and setup your Rhino engine in the actor in such a way that it will stop itself if it has been executing for too long. That failure will kick out to the supervisor (if pooled) and cause that pooled instance to be restarted which will init a new Rhino in preStart. This might be the best approach for dealing with the possibility of long running scripts.