I'm trying to find the proper pattern for initializing an actor asynchronously, so that I can look up dependent ActorRefs it needs. I want to avoid using ActorSelection, since it's
ambiguous as to the number of actors it points to, and
has some overhead that's undesirable for many tells
Looking at the Actor LifeCycle it seems to be all pretty much synchronous until the message loop starts, including preStart, etc., which leads me to think that I have only one of two choices:
Use a factory method with a signature of Future[ActorRef]
All dependencies for constructing the actor are resolved asynchronously and passed in via Props.
The main problem with this approach is that you cannot use this factory to construct an actor inside of another actor, since it then has the same problem, i.e. it's turtles all the way down, wiring up the hierarchy of all actors and their dependencies asynchronously.
Use become and stash to transition the actor
The actor is created with actorOf, immediately resulting in an ActorRef but it starts in an Initialization state, does it's dependency resolution, stashing incoming messages in the meantime, and finally becomeing the Running state and unstashAlling.
This feels a lot more idiomatic for actors, even though my dependencies will all be var instead of val.
Both seem like a lot of overhead, making me wondering if I these are the best options or if I just haven't found the proper pattern in the docs.
There's no reason your dependencies have to be vars when using become:
val initializing: Actor.Receive = {
case Dependencies(d1, d2) => context.become(working(d1, d2))
}
def working(d1: Dependency, d2: Dependency): Actor.Receive = {
case msg => d1.fetch(...) // whatever
}
def receive = initializing
Also, actorFor is a) deprecated and b) doesn't create an actor.
Related
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.
I'm working on implementing a small language to send tasks to execution and control execution flow. After the sending a task to my system, the user gets a future (on which it can call a blocking get() or flatMap() ). My question is: is it OK to send futures in Akka messages?
Example: actor A sends a message Response to actor B and Response contains a future among its fields. Then at some point A will fulfill the promise from which the future was created. After receiving the Response, B can call flatMap() or get() at any time.
I'm asking because Akka messages should be immutable and work even if actors are on different JVMs. I don't see how my example above can work if actors A and B are on different JVMs. Also, are there any problems with my example even if actors are on same JVM?
Something similar is done in the accepted answer in this stackoverflow question. Will this work if actors are on different JVMs?
Without remoting it's possible, but still not advisable. With remoting in play it won't work at all.
If your goal is to have an API that returns Futures, but uses actors as the plumbing underneath, one approach could be that the API creates its own actor internally that it asks, and then returns the future from that ask to the caller. The actor spawned by the API call is guaranteed to be local to the API instance and can communicate with the rest of the actor system via the regular tell/receive mechanism, so that there are no Futures sent as messages.
class MyTaskAPI(actorFactory: ActorRefFactory) {
def doSomething(...): Future[SomethingResult] = {
val taskActor = actorFactory.actorOf(Props[MyTaskActor])
taskActor ? DoSomething(...).mapTo[SomethingResult]
}
}
where MyTaskActor receives the DoSomething, captures the sender, sends out the request for task processince and likely becomes a receiving state for SomethingResult which finally responds to the captured sender and stops itself. This approach creates two actors per request, one explicitly, the MyTaskActor and one implicitly, the handler of the ask, but keeps all state inside of actors.
Alternately, you could use the ActorDSL to create just one actor inline of doSomething and use a captured Promise for completion instead of using ask:
class MyTaskAPI(system: System) {
def doSomething(...): Future[SomethingResult] = {
val p = Promise[SomethingResult]()
val tmpActor = actor(new Act {
become {
case msg:SomethingResult =>
p.success(msg)
self.stop()
}
}
system.actorSelection("user/TaskHandler").tell(DoSomething(...), tmpActor)
p.future
}
}
This approach is a bit off the top of my head and it does use a shared value between the API and the temp actor, which some might consider a smell, but should give an idea how to implement your workflow.
If you're asking if it's possible, then yes, it's possible. Remote actors are basically interprocess communication. If you set everything up on both machines to a state where both can properly handle the future, then it should be good. You don't give any working example so I can't really delve deeper into it.
I have an actor which takes the result from another actor and applies some check on it.
class Actor1(actor2:Actor2) {
def receive = {
case SomeMessage =>
val r = actor2 ? NewMessage()
r.map(someTransform).pipeTo(sender)
}
}
now if I make an ask of Actor1, we now have 2 futures generated, which doesnt seem overly efficient. Is there a way to provide a foward with some kind of continuation, or some other approach I could use here?
case SomeMessage => actor2.forward(NewMessage, someTransform)
Futures are executed in an ExecutionContext, which are like thread pools. Creating a new future is not as expensive as creating a new thread, but it has its cost. The best way to work with futures is to create as much as needed and compose then in a way that things that can be computed in parallel are computed in parallel if the necessary resources are available. This way you will make the best use of your machine.
You mentioned that akka documentation discourages excessive use of futures. I don't know where you read this, but what I think it means is to prefer transforming futures rather than creating your own. This is exactly what you are doing by using map. Also, it may mean that if you create a future where it is not needed you are adding unnecessary overhead.
In your case you have a call that returns a future and you need to apply sometransform and return the result. Using map is the way to go.
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.
Depending on a reply from a Scala Actor seems incredibly error-prone to me. Is this truly the idiomatic Scala way to have conversations between actors? Is there an alternative, or a safer use of reply that I'm missing?
(About me: I'm familiar with synchronization in Java, but I've never designed an actor-based system before and don't yet have a full understanding of the paradigm.)
Example mistakes
For a trivial demonstration, let's look at this silly integer-parsing Actor:
import actors._, Actor._
val a = actor {
loop {
react {
case s: String => reply(s.toInt)
}
}
}
We could intend to use this as
scala> a !? "42"
res0: Any = 42
But if the actor fails to reply (in this case because a careless programmer did not think to catch NumberFormatException in the actor), we'll be waiting forever:
scala> a !? "f"
We also make a mistake at the call site. This next example also blocks indefinitely, because the actor does not reply to Int messages:
scala> a !? 42
Timeout
You could use !? (msec: Long, msg: Any) if the expected reply has some known reasonable time bound, but that is not the case in most circumstances I can think of.
Guaranteeing reply
One thought would be to design that actor such that it necessarily replies to every message:
import actors._, Actor._
val a = actor {
loop {
react {
case m => reply {
try {
m match {
case s: String => reply(s.toInt)
case _ => None
}
} catch {
case e => e
}
}
}
}
}
This feels better, although there is still a little fear of accidentally invoking !? on an actor is no longer acting.
I can see your concerns, but I would actually argue that this is not any worse than the synchronization you are used to. Who guarantees that the locks will ever be released again?
Using !? is at your own risk, so no there are no 'safer' uses that I am aware of. Threads can block or die and there is absolutely nothing we can do about it. Except for providing safety-valves that can soften the blow.
The event-based acting actually gives you alternatives to receiving replies synchronously. The timeout is one of them but another thing such as Futures via the !! method. They are designed to handle deadlocks such as that. The method immediately returns a future that can be handled later.
For inspiration and more in-depth design decisions see:
Actors:
http://docs.scala-lang.org/overviews/core/actors.html
Futures (in scala 2.10):
http://docs.scala-lang.org/sips/pending/futures-promises.html
Don't bother with old local actors - learn Akka. Also it's good that you know about synchronized, but personally me - almost never use such a word, even in Java code. Imagine synchronized is deprecated, learn Java memory model, learn CAS.
I am not familiar with the Actor system in the Scala standard library myself, but I highly recommend checking out the Akka toolkit (http://akka.io/) which has "replaced" the Scala Actors and comes with the Scala distribution as of Scala 2.10.
In terms of Actor system design in general, some of the key ideas are asynchronous (non-blocking), isolated mutability, and communication via message passing. Each Actor encapsulates it's own state, nobody else is allowed to touch it. You can send an Actor a message that may "ask" it to change state, but the Actor implementation is free to ignore it. Messages are sent asynchronously (you CAN make it blocking, not recommended). If you want to have some sort of "response" (so that you can associate a message with a previously sent message), the Future API in Scala 2.10 and ask of Akka can help.
Regarding your error format exception and the problem in general, consider looking at the ask and Future API in Scala 2.10 and Akka 2.1. It will handle exceptions and is non-blocking.
Scala 2.10 also has a new Try that is intended as an alternative to the old-fashioned try-catch clauses. The Try has an apply method that you would use like any try (minus the catch and finally). Try has two sub-classes Success and Failure. An instance of Try[T] will have subclasses Success[T] and Failure[Throwable]. It is easier to explain by example:
>>> val x: Try[Int] = Try { "5".toInt } // Success[Int] with encapsulated value 5
>>> val y: Try[Int] = Try { "foo".toInt } // Failure(java.lang.NumberFormatException: For input string: "foo")
Since Try does not throw the actual exception and the subclasses are conveniently case-classes, you could easily use the result as a message to an Actor.