How to create routers in akka with parameterized actors? - scala

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 .

Related

Akka HTTP: How to split routes with actors

I have an old Scala/Akka Http project that I'm trying to simplify and refactor. I was wondering if there's a better way to organize routes and perhaps split them across actors. Here's what I have at the moment (far from ideal):
```
object MyAPI {
def props(): Props = Props(new MyAPI())
val routes = pathPrefix("api") {
pathPrefix("1") {
SomeActor.route //More routes can be appended here using ~
}
}
}
final class MyAPI extends Actor with ActorLogging {
implicit lazy val materializer = ActorMaterializer()
implicit lazy val executionContext = context.dispatcher
Http(context.system)
.bindAndHandleAsync(Route.asyncHandler(MyAPI.routes), MyHttpServer.httpServerHostName, MyHttpServer.httpServerPort)
.pipeTo(self)
override def receive: Receive = {
case serverBinding: ServerBinding =>
log.info(s"Server started on ${serverBinding.localAddress}")
context.become(Actor.emptyBehavior)
case Status.Failure(t) =>
log.error(t, "Error binding to network interface")
context.stop(self)
}
}
```
```
object SomeActor {
def props(): Props = Props[SomeActor]
val route = get {
pathPrefix("actor") {
pathEnd {
complete("Completed") //Is there a clean way 'ask' the actor below?
}
}
}
}
class SomeActor extends Actor with ActorLogging {
implicit lazy val executionContext = context.dispatcher;
override def receive: Receive = {
//receive and process messages here
}
```
So, my question is - is there a clean way to structure and refactor routes instead of lumping them together in one large route definition? I could perhaps create a hierarchy of actors (routers) and the main route definition just delegates it to the routers and we incrementally add more details as we go deeper in the actor hierarchy. But is there a generally accepted patter or two to organize routes?
I would like to suggest you on the basis of the functionality you can have as many actors you you want, but create one supervisor actors which will keep watch on each child actor. And all the supervision strategies should be written into the supervisor itself, and all the msg you gonna sent to the actors should be forwarded by the supervisor.
As soon as you get the data from the end point, may be get or post method take the data into someRequest case class. Then sent it to some handleReq() method. And then do your processing make traits on functionality basis.
You can structure project something like this.
src/
actor//all the actors will be in this package
model// all the case classes and constants
repo// all the db related function you can do here
service// all your routes and endPoint functions
Now you can have package util where all the utilities trait you can put which will be used by any of the actor, or service may be you have lots of validations you can have a package named validator.
The structure is depends on your business. I think it would help.

Akka HTTP Code/Structural Patterns

I am just starting with Akka Http (and Scala) and was wondering if there are any well-defined patterns for structuring Akka code. In particular, I am looking for structural patterns for composing/aggregating routes dynamically. In particular, I'm looking for a solution similar to the below pseudocode:
trait MyActor extends Actor {
val myRouter: ActorRef = context.actorOf(FromConfig.props(Props[MyWorker]), "Worker")
val myRoute = .... //route definition for this trait
}
trait MySecondActor extends Actor {
val mySecondRouter: ActorRef = context.actorOf(FromConfig.props(Props[MySecondWorker]), "SecondWorker")
val myRoute = .... //route definition for this trait
}
Then, in my main server just mix in the traits to get both actors and routes automagically:
class HttpServer extends SomeTrait with MyActor with MySecondActor {
.....
.....
}
There are some obvious problems with the above pattern including:
All traits inherit from Actor and then mix into the same class - not sure what the final behaviour will be.
The HttpServer class itself becomes an actor and cannot be instantiated by new HttpServer()
The routes are not concatinated.
What I'm looking for is a pattern that:
Allows me to separate routing logic in various packages and preferable bundle it with corresponding actors.
Make routes dynamic and discoverable instead of specifying them at boot time.
I came across the following two on StackOverflow but was wondering if there's a better approach and a well-defined pattern:
akka-http with multiple route configurations (This isn't really dynamic)
How to aggregate akka-http routes using a trait? (Old question using reflection)
Thanks!
When using akka-http you usually don't need actors to implement the routing. Actors are usually only used to access the business logic asynchronously. Let me give you an example on how to structure your code with predefined routes. This is the pattern I learned from Heiko Seeberger.
First create an object creating your routes:
object Api {
def route: Route = {
import import akka.http.scaladsl.server.Directives._
pathSingleSlash {
get {
complete(StatusCodes.OK)
}
}
}
}
If you need an actor to access your business logic you can pass it as parameter to the route method. Remember to use the ask pattern, when interacting with actor during request handling.
Than you create a Root actor which creates your Api:
final class Root extends Actor with ActorLogging {
Http(context.system)
.bindAndHandle(Api.route, "0.0.0.0", 8000)
.pipeTo(self)
override def receive: Receive = {
case s: ServerBinding =>
log.info(s"Listening to ${s.localAddress}")
context.become(Actor.emptyBehavior)
case Status.Failure(t) =>
log.error(t, "Error binding to network interface")
context.stop(self)
}
}
Finally you need some main method to create the actor system and the Root actor:
object Main {
def main(args: Array[String]): Unit = {
val system = ActorSystem("user-api")
system.actorOf(Props(new Root))
Await.ready(system.whenTerminated, Duration.Inf)
}
}
So this would be my take on best practices for defining akka-http routes. What is not covered in my answer is how to dynamically discover routes, but to be honest, I fail to see the use case here. Usually your system should have some well defined end points. How would users know which endpoints they can talk to if even the system does not know which endpoints it will serve at startup time?

How to pass a class as a parameter for instantiation in Scala

I am trying to refactor an Akka application from a single tier to multi-tier structure with akka clustering (http://doc.akka.io/docs/akka/2.3.9/scala/cluster-usage.html). Within the application are some actors that have a parameterized default constructor, e.g.
class MyActor(someParam: boolean = true) extends Actor {
def receive = { /* message handling here... */ }
}
I am now trying to create a generic router actor that will route to a node with a specific node. The cluster configuration is working based of the example on the akka site, and I can create a router in 1 role that routes to the actor in another role:
class MyActorProxy extends Actor {
val workerRouter = context.actorOf(FromConfig.props(Props(classOf[MyActor]), name = "workerRouter")
def receive = {
case msg: Any =>
val currentSender = sender()
workerRouter.tell(msg, currentSender)
}
}
This method works as needed. However, I need to go and create a handful of proxy classes with the same functionality, and it's painful. I'm trying to make it work better, and limited scala experience is making it difficult. Here's what I am trying to do:
abstract class RouterProxy[T <: Actor](routerPath: String) extends Actor {
val router = context.actorOf(FromConfig.props(Props(classOf[T])),name=routerPath)
def receive = {
case msg: Any => {
val currentSender = sender()
router.tell(msg,currentSender)
}
}
}
class MyActorProxy extends RouterProxy[MyActor](routerPath = "myActorRouter")
Have come up with this by reading through some scala docs and through stackoverflow, but can't seem to get it right - this approach doesn't let me create the props for the actor. I've seen How to instantiate an instance of type represented by type parameter in Scala and I think that the type information is being lost (type erasure).
How would I go about passing an actor class to the router proxy to allow for router initialization?
This is the error I get during compilation, while initializing the router:
class type required but T found
edit
Background for using a generic proxy router
The reason for this approach is to refactor the application for both single tier and multi-tier architecture. When running multi-tier, I want to skip initializing any "heavy" actors. Given I have the following config on a frontend node:
akka.actor.deployment {
/workerRouter {
routee.paths = ["/user/myActor"]
cluster.use-role = backend
}
}
akka.cluster.roles = [frontend]
and the backend node has roles of [backend], then when I start up frontend nodes, MyActor will not be initialized. MyActor is an example of 1 of many actors that are supervisors / managers. Each 1 of them might initialize a few other actors in turn (sometimes with routers). What I'm trying to do is refactor the application so I can run lightweight frontend nodes in a different tier to resource heavy backend nodes if I need to, but also still have the ability to run all on a single node. By this approach, I can add in initialization for heavy managers into my application bootstrap and add a role and it becomes a multifunctional app without needing recoding.
edit 2
I am able to get the application to work as expected if the class constructor doesn't take any arguments.
MyActor extends Actor { /* ... */ }
And then in my abstract class:
abstract class RouterProxy[T <: Actor](routerPath: String) extends Actor {
val router = context.actorOf(FromConfig.props(Props[T]),name = routerPath)
}
Props[MyActor] works fine for a parameterless actor, but Props(classOf[T]) looses the type.
You don't actually have to define another class for the router, you can do it all through your configuration file:
val myActorRouter = system.actorOf(Props[MyActor]
.withRouter(FromConfig())
,"workerRouter")
Where "workerRouter" is defined in your application.conf file like this:
akka.actor.deployment {
/workerRouter {
router = round-robin
nr-of-instances = 5
}
}
You can also configure it all through code if you have a pretty simple configuration:
val myActorRouter = system.actorOf(Props[MyActor].withRouter(
RoundRobinRouter(nrOfInstances = 5)))
Either way you end up with myActorRouter as an actor ref you can send messages to. In the background the Akka system has created a pool of MyActor actors and forwards the messages to them. The router takes itself out of the response so you don't need to spoof the sender like you've done: when a routee sends a message to sender it goes directly back to the actor that sent the message to the router.

InvalidActorNameException - actor name {name} is not unique

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)

Creating multiple actors in 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!