Creating multiple actors in scala - scala

I'm new to scala and I'm trying to write a program in scala which creates multiple (say, 30) actors and passes messages between them.
Below is what i have managed till now:
import scala.actors.Actor
import scala.util.Random
class MyActor(val id:Int, val N:Int) extends Actor {
def act() {
println ("Starting actor: " + id)
/**
react{
case str : String =>
println("Received Msg: " + str)
val randNo : Int = Random.nextInt(N)
println("Actor " + id + " Picking a random actor: " + randNo)
// Here, I should forward the message received to the ALREADY created and started actors
// val objActor = new MyActor(randNo : Int, N : Int)
// objActor.start
// objActor ! str
}
*/
}
}
object Main {
def main(args:Array[String]) {
if(args.length == 0)
{
println("Usage scala Main <numNodes>")
sys.exit()
}
val N : Int = (args(0)).toInt
// Starting all actors
for (i: Int <- 0 to N-1) {
val a = new MyActor(i : Int, N : Int)
println ("About to start actor " + a.id)
a.start
// a!"Broadcast this msg to all actors"
}
}
}
The objective of the program is to create multiple actors and forward a string from one actor to another.
The above code creates 'N' number of actors given as command line argument.
These actors are created and started by the object Main.
Main should send a message to ONLY ONE of the above created actors.
The actor which receives the message from the Main should forward the same message to another ALREADY created/started actor.
Is this possible? If so, can you please guide me on the right direction?
Thanks in advance,
MS

First off, I would suggest checking out Akka actors, soon to replace Scala actors in Scala 2.10 which is hopefully coming out in the next few months.
That being said, it definitely is possible, the workflow would go something like this (in Akka at least):
Create an ActorSystem in your main method.
Spawn Actor as desired within the ActorSystem via the actorOf method, which will return an ActorRef object.
Pick one of these ActorRef's to send the message to.
In the Actor implementation, somehow make the Actor aware of the others (perhaps via the constructor), and figure out how you want the propagate the String throughout the system (on this note, I generally prefer using Scala case classes as messages).
This sort of sounds like a state machine like system - one idea off the top of my head that I've been playing with is to treat the ActorSystem as a graph entity, meaning for each Actor instance you pass it a list of it's neighbors (perhaps as a Vector[ActorRef]).
You can also check out the new Actors DSL the Akka team recently introduced.
For learning more about Akka, I recommend the resources:
Jonas Bonér's recent talk at NY Scala introducing Akka
Akka in Action (MEAP)

I found a way to do the above stated problem in scala itself by using an array of actors.
since all the actors are going to perform the same operation (i.e.,) forwarding the message, it is enough to create multiple instances of MyActor.
Thanks a lot!

Related

Create an actor if it does not exists in scala akka cannot find the actor

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

akka: using akka-typed to implement the active objects pattern

The Akka Typed Actors documentation states that it will be superseded by Akka Typed. I am inferring from this that Akka Typed can be used to implement the Active Object pattern; but it is not too clear to me how. Here is my attempt so far; I'm aware it stinks :D
object HelloWorld {
final case class Greet(whom: String, replyTo: ActorRef[Greeted])
final case class Greeted(whom: String)
private val greeter = Static[Greet] { msg ⇒
println(s"Hello ${msg.whom}!")
msg.replyTo ! Greeted(msg.whom)
}
private val system = ActorSystem("HelloWorld", Props(greeter))
def greet(whom: String): Future[Greeted] = system ? (Greet(whom, _))
}
Cheers
The Active Object Pattern as defined by the page you link to is not desirable for all the reasons why TypedActors are being removed: the fact that a method is executed asynchronously is so important that it should not be hidden by technologies like proxy objects that implement normal interfaces. Instead, Akka Typed allows you to write nearly the same code as if it was an Active Object while retaining the asynchronous marker: instead of selecting a method with the . syntax you send a message using ? (or ! if the protocol is not simple request–response). Your example would look like this:
object HelloWorld {
final case class Greet(whom: String)(replyTo: ActorRef[Greeted])
final case class Greeted(whom: String)
val greeter = Static[Greet] { msg ⇒
println(s"Hello ${msg.whom}!")
msg.replyTo ! Greeted(msg.whom)
}
}
object Sample extends App {
import HelloWorld._
val system = ActorSystem("HelloWorld", Props(greeter))
val fg = system ? Greet("John")
}
Please note that creating a separate thread (or ActorSystem) per object may sound okay as per the classical pattern, but doing that foregoes many of the benefits of a message-driven architecture, namely that many Actors can share the same resources for more efficient execution and they can form supervision hierarchies for principled failure handling etc.

How to create routers in akka with parameterized actors?

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 .

Uniquely identifying actors in scala

I'm building a simple logging class in scala which would write all log information to a file. This is part of a homework assignment. Hence I cannot use the already available loggers in java or scala or akka libraries. Can any of you please tell how to uniquely identify actors in scala i.e., is there a resource ID or any other ID for each actor. If so, how can it be accessed?
I tried using hashCode() on the actor objects. But it does not give the expected result, as the value changes for each object and many objects can be created for a single actor.
If you are using akka actors you can get the name of the actor by looking at self.path (self is an ActorRef)
http://doc.akka.io/api/akka/2.0.4/#akka.actor.ActorPath
EDIT:
If you are using scala actors then you could do something like...
class MyActor(name: String) extends Actor {
def act() {
receive {
case _ => println("Message on actor: " + name)
}
}
}
val actor1 = new MyActor("actor1")
val actor2 = new MyActor("actor2")

Message passing using Actors

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