Why when I select an absolute path with ActorContext it doesn't works (the actor isn't correctly selected and doesn't receive the HelloResponse message) ?
//From Actor2:
//This doesn't work (Message never received)
context.actorSelection("/user/actor1") ! HelloResponse("hello back1")
//This works (actor 1 receives the message)
context.system.actorSelection("/user/actor1") ! HelloResponse("hello back2")
I'm newbie to Scala/Akka but reading documentation it seems that should work.
This is a bug, thanks for asking: https://www.assembla.com/spaces/ddEDvgVAKr3QrUeJe5aVNr/tickets/3276
When you use context.actorSelection inside of an actor, what you are saying is find an actor under this current actors control (started by/supervised by). Since actor1 was probably not started by actor2 (or is not supervised by actor2), then it won't resolve to anything. If actor1 was actually owned/started by actor2 then you could probably do context.actorSelection("/actor1") to get that child actor of actor2. The reason context.system.actorSelection works is because you are going all the way "up" to system first before starting your search and fully qualifying the path to the actor. System "owns" actor1 if you started it up as system.actorOf, so using that path will allow you to get to it starting from system.
A little code to show what I mean:
class Actor1 extends Actor{
override def preStart = {
context.actorOf(Props[Actor2], "actor2")
}
def receive = {
case _ =>
}
}
class Actor2 extends Actor{
override def preStart = {println("my path is: " + context.self.path)}
def receive = {
case _ =>
}
}
object FutureTesting {
def main(args: Array[String]) {
val sys = ActorSystem("test")
implicit val ec = sys.dispatcher
//Starting an Actor2 from system
sys.actorOf(Props[Actor2], "actor2")
//Starting an Actor1 from system which in turn starts an Actor2
sys.actorOf(Props[Actor1], "actor1")
}
}
When you run this example, you will see:
my path is: akka://test/user/actor1/actor2
my path is: akka://test/user/actor2
So you can see that I have 2 instances of Actor2 running in my system; one spawned directly from sys tied to /user/actor2 as it's lookup path and one started from an instance of Actor1 tied to /user/actor1/actor2 for its path.
The actor system is hierarchical and this example shows that. The ActorSystem itself is the root to everything. Selecting actors is then similar to XPath in that the context that you are issuing the select from matters.
From actor2 you will need to use
context.actorSelection("/actor1")
I agree it is not intuitive given the metaphor is a filesystem and when using a filesystem a leading / is an absolute path meaning start at the root. Also it is inconsistent with actorFor because
context.actorFor("/user/actor1")
returns the top level Actor1 (see Absolute and Relative Paths)
EDIT - this was a bug that was fixed in Akka 2.1.4 (see Roland's answer). From 2.1.4 onwards you can use context.actorSelection("/user/actor1").
Related
For some reason I have to use gRPC and Akka at the same time. When this actor is started as a top actor, nothing goes wrong (in this little demo). But when it becomes a child actor, it cannot receive any messages, and the following is logged:
[default-akka.actor.default-dispatcher-6] [akka://default/user/Grpc] Message [AkkaMessage.package$GlobalStart] from Actor[akka://default/user/TrackerCore#-808631363] to Actor[akka://default/user/Grpc#-1834173068] was not delivered. [1] dead letters encountered.
The example core:
class GrpcActor() extends Actor {
val ec = scala.concurrent.ExecutionContext.global
val service = grpcService.bindService(new GrpcServerImpl(), ec)
override def receive: Receive = {
case GlobalStart() => {
println("GlobalStart")
}
...
}
}
I tried to create a new ExecutionContext like:
scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
Why is this happening, and how do can I debug a dead letters problem like this (no exception is thrown)?
Update:
Sorry I didn't list everything here. I used normal Main method to test GrpcActor as top actor, and ScalaTest to test it as child actor, which is a mistake.
class GrpcActorTest extends FlatSpec with Matchers{
implicit val system = ActorSystem()
val actor: ActorRef = system.actorOf(Props[GrpcActor])
actor ! GlobalStart()
}
It is this empty test suite that active shutdown the whole actor system. But the problem is with this line
val service = grpcService.bindService(new GrpcServerImpl(), ec)
the delivery of GlobalStart() was delayed after the shutdown.
Without that line, message can be delivered before the shutdown.
Is this a normal behavior?
(My guess: it happened that the GlobalStart() was queued after the shutdown message with that line, which did some heavy work and made the difference in time)
One way to address the problem is to make service a lazy val:
class GrpcActor extends Actor {
...
lazy val service = grpcService.bindService(new GrpcServerImpl(), ec)
...
}
A lazy val is useful for long-running operations: in this case, it defers the initialization of service until it is used for the first time. Without the lazy modifier, service is initialized when the actor is created.
An alternative approach is to add a Thread.sleep in your test to prevent the actor system from shutting down before the actor has fully initialized:
class GrpcActorTest extends FlatSpec with Matchers {
...
actor ! GlobalStart()
Thread.sleep(5000) // or whatever length of time is needed to initialize the actor
}
(As a side note, consider using the Akka Testkit for your actor tests.)
Add a supervisor strategy to its parent, add println to the actor lifecycle. There is something that kill your actor . Finally, if you provide a complete example maybe I can say more :)
Based on this solution I have implemented the following, but it throws an exception saying that the actor with that name already exists:
implicit val timeout = Timeout(5 seconds)
val pathToLookup: String = self.path.toString + "/" + actorName
context.actorSelection(pathToLookup).resolveOne().onComplete(useActor)
def useActor(possible: Try[ActorRef]) = {
val definite = possible match {
case Success(actor) =>
log.debug("Found an actor " + actorName)
actor
case Failure(_) =>
log.debug("Creating a new actor " + actorName)
context.actorOf(Props[MyActor], name = actorName)
}
// other code
}
I have a feeling that I am not passing the right path to actorSelection but I do not see how to fix it.
Edit: I corrected the path of the child actor, and it still does not find the actor. I also tried toStringWithoutAddress but it does not work either.
ActorySystem.actorOf(props) creates top level actors, that will be directly under /user/ while context.actorOf(props) inside of an actor creates actors as children of that actor so they will have the path /user/path/to/parent/child.
The problem is that you are looking for the actors under /user/[name] but you are creating them as children of your current actor, so they will be at something like /user/myactor/[name].
Also note, that you are closing over actor state and using internal actor things from a different thread which is unsafe when you are using onComplete and context like that. See the warning in this section about that: http://doc.akka.io/docs/akka/2.4.1/scala/actors.html#Ask__Send-And-Receive-Future
I am trying to use a broadcast router in Scala, if I'm not mistaken it should look like this:
val system = ActorSystem("My beautiful system")
val workerRouter = system.actorOf(Props[Agent].withRouter(BroadcastRouter(individualDefinitions.size)), name = "agentRouter")
That is what I understand from the tutorial I am following.
The workerRouter acts as another actor and I can send messages to this router that will send them to all the Agents (as many as individualDefinitions I have).
The problem is that I'd like to use the individual definitions to build the agents, they actually take some parameters in the constructor and those parameters are in the individualDefinitions.
Q: How could I tell the router to pass those parameters to each one of them as part of the constructor?
Please note each actor should get one individualDefinition and they are all different. I cannot use the solution in a related question where the constructor receives constants: In Akka Java actor model, can a router create actors with non-default constructor?
Please note that here each actor should have different parameters, if one of them is restarted it should get the same parameters it got in the first place. I don't know if that solution could be modified to do that.
A possible solution could be using an actor as the router, to separate creation (constructor) and routing, as in question Akka (java), non blocking broadcast to all children.
I'm not sure that is the "right" approach in this case. Using an actor as the router has several problems (besides of elegance). I am concerned about the actor that works as a router being restarted and losing all its subscribers. If the actor is restarted in half of a loop some actors could also miss some messages if I'm not mistaken.
Thank you.
You can create routers by specifying as routees some already created actors, constructed by whatever logic.
The following example will create 2 actors created differently and then create a round robin router which will route the messages to them.
class MyActor(param1: String) extends Actor with ActorLogging {
def receive: Actor.Receive = {
case msg => log.info("Message from {}: {}", param1, msg)
}
}
object MyActor {
def apply(param: String): Props = Props(new MyActor(param))
}
object Main extends App {
val system = ActorSystem()
val a1 = system.actorOf(MyActor("actor1"))
val a2 = system.actorOf(MyActor("actor2"))
val routerProps = Props.empty.withRouter(RoundRobinRouter(routees = Vector(a1, a2)))
val router = system.actorOf(routerProps)
for (i <- 1 to 10) {
router ! i
}
readLine()
system.shutdown()
}
More details here: http://doc.akka.io/docs/akka/2.2.0/scala/routing.html
public class Master extends UntypedActor {
-----
-----
public Master() {
workerRouter = this.getContext().actorOf(Worker.createWorker().withRouter(new RoundRobinRouter(8)), "workerRouter");
}
With Akka 2.4.2, we can simply use:
workerRouter = this.getContext().actorOf(new RoundRobinPool(noOfWorkers).props(Props.create(Worker.class)), "workerRouter");
This is best Effort code executed in min. time in akka .
So I'm getting started using Akka actors inside of my Play 2.0 app. I noticed quickly that repeated calls to sending messages to the same actor, specified via:
val myActor = Akka.system.actorOf(Props[MyActor], name = "myactor")
Resulted in InvalidActorNameException.
I then started reading up on the creation of Actors in this doc
The doc seemed to recommend creating a "master" Actor class with all of the individual actors specified in there. The receive of this actor class would, in turn, match on the message and delegate the message to the appropriate Actor.
So I tried this and now have something like:
class MasterActor extends Actor{
import context._
val emailActor = actorOf(Props[EmailActor], name = "emailActor")
protected def receive = {
case reminder : BirthdayReminder => emailActor ! reminder
}
}
Problem is that I'm in the same situation I was before. I don't know how to avoid the InvalidActorNameException when I try something like:
val myActor = Akka.system.actorOf(Props[MasterActor], name = "MasterActor")
myActor ! BirthdayReminder(someBirthday)
So what's the right way to organize my Actors?
If you want only one MasterActor, why are you creating multiple ones? You should just look up the one you have already created:
val actorRef = context.actorFor("MasterActor")
actorRef ! BirthdayReminder(someBirthday)
I am writing a program using Actors in scala in which an actor (Actor1) accepts two numbers as command line arguments and sends a message to another actor Actor2 (which calculates their sum). Actor2 sends the result to Actor1, who prints it on the screen.
class Actor1 extends Actor {
def main(args: Array[String]) {
val n= Integer.parseInt(args(0))
val k= Integer.parseInt(args(1))
val actor2 = new Actor2
actor2 ! (n, k)
}
def act()
{
react{
case num: Integer =>
println(num)
case _=>
println("Sum not received")
exit
}
}
}
class Actor2 extends Actor {
def act(){
loop
{
react
{
case(n:Int, k:Int) =>
val i = n + k
val actor1 = new Actor1
actor1 ! i}
}
}
}
Is it possible to define main() inside the class that extends Actor, and is there any other way to accept command line arguments by the Actor?
It shows the error: class Actor1 needs to be abstract, since method act in trait Reactor of type ()Unit is not defined.
First things first: You should consider using akka instead of the default Scala actors. It's just better.. in pretty much every aspect.
That aside, here are a few answers for your:
Your main method should be in a standalone object (not a companion object). So use something like this: object Main { def main(args:Array[String]) { ... } } and start your program via the Main object/class. (This is due to the definition inside the Actor1 class being non-static and the problem that if you define a companion object the .class filenames collide.)
In your code, something seems to have gone wrong with the brackets - or did you place Actor2 inside the Actor1 class on purpose? It's cleaner, if you just make three separate classes/objects: Actor1, Actor2, Main.
When you create Scala actors, you have to explicitly start them (not so with akka 2.x). So you miss your calls to actor1.start and such. Note that your program will then not terminate before your actors have terminated, so don't wonder if it doesn't stop anymore after you add that.
Finally, some minor hints:
You may want to consider using !? and send back your answer to the original caller, as this also allows you to have a proper termination condition.
Integer.parseInt("0") can be written more simply as "0".toInt