I'm trying to familiarize myself with Akka using a pet project. This is basically a tournament-style server, having a pool of players. On each round, it should fetch two random players from the pool, play them against each other, then update a scoreboard. The whole thing sits behind an HTTP server. Players are added via an HTTP Post message, and games are triggered via a 'Play' message that's to be sent from a JS client.
The way I thought of implementing it is as follows:
a PlayerPool actor handling two messages, 'AddPlayer' and 'Play'
a Round actor that takes a message with two players, plays a round, then updates the
GameResults actor, containing a list of played rounds and the winner of each round. It also sports the 'GetScore' message which returns the scoreboard.
The HTTP layer is a Spray Routing actor, exposing calls for 'GetScore', 'AddPlayer' and 'Play', talking to the PlayerPool and GameResults actors.
My problem is that two separate actors are talking to GameResults - both Spray directly, and the Round actor, and apparently two separate instances of GameResults are being created, so that while Round adds a result to one instance, Spray is reading the scoreboard from another instance. Obviously I'm missing something very basic and before attempting to resolve the issue, I'd like to understand what's the canonic way of doing this in Akka? basically this problem can be reduced to an actor that holds a state across different calls.
Would be glad to have someone point me in the right direction.
code snippet example how to pass messages from spray to your game result actor :
hope this helps
object SomeApp extends App{
//create a actor system
val yourSystem = ActorSystem("Your-System")
//init spray actor
val restHandler = yourSystem.actorOf(Props[RestHandler], name = "Rest-spray")
//init play pool actor
val playerPoolActor = yourSystem.actorOf(Props[PlayerPool], name = "playerPool")
//INIT ONLY 1 game result actor
val gameResultsActor = yourSystem.actorOf(Props[GameResults], name = "gameResults")
//spray listen to all IP on port 90210
IO(Http)(yourSystem) ! Http.Bind(restHandler, interface = "0.0.0.0" , port = 90210)
class RestHandler extends Actor with RestHandlerRoute {
def actorRefFactory = context
//nice to hold the route in a diffrent trait
def receive = runRoute(someRoute)
}
}
//only thing the trait is doing is configuring the routing and send message to relavant actor
trait RestHandlerRoute extends HttpService{me: Actor =>
import SomeApp._
val someRoute =
path("getGameResults") { get { respondWithMediaType(`text/html`) { complete {
//case the user requested http://someIP:90210/getGameResults spray will send a message to the game result actor
gameResultsActor ! getResult
} ~
}
Related
I am using (learning to) handle websockets in play application.
My controller is using WebSocket.acceptWithActor
def clientWS = WebSocket.acceptWithActor[JsValue, JsValue] { _ =>
upstream => ClientSesssionActor.props(upstream)
}
and all is well except some other "supervisor" actor needs to be able to use context.actorSelection(...) to communicate with all/some of those ClientSessionActors.
But all my ClientSessionActors are created with a path like this one :
[akka://application/system/websockets/ REQ_ID /handler]
Here is the line where WebsocketActorSupervisor creates them :
val webSocketActor = context.watch(context.actorOf(createHandler(self), "handler"))
That is where the "handler" part of the path comes from.
I would like to pass in a specific name for my ClientSessionActor instead of getting "handler".
Overloading the whole call stack with one more parameter seems inelegant: there is WebSocketActor.scala with Connect, WebSocketActorSupervisor(props and constructor), WebSocketsActor receive and then everything inside the WebSocket.scala.
I know I can pass the supervisor reference to the props, but what about the case when the "supervisor" has been restarted and needs to reconnect with his minions.
One more thing, I realize that I might be able to get all the "handler" actors, but there are more than 2 kinds of handlers. Yes I could have them ignore msgs directed at the other groups of handlers but this just feels so redundant sending out 3 times more msgs than I should have to.
Any suggestions ?
James ? :)
Thank you
How about each ClientSesssionActor sends a Register message to supervisor on preStart and store them in eg. val sessions = new HashMap[String, ActorRef].
And then unregister by sending Unregister in postStop
private class WebSocketsActor extends Actor {
import WebSocketsActor._
def receive = {
case c # Connect(requestId, enumerator, iteratee, createHandler) =>
implicit val mt = c.messageType
context.actorOf(WebSocketActorSupervisor.props(enumerator, iteratee, createHandler),
requestId.toString)
}
}
Here is code how play creates actors for handling websockets, it names with requestId.
I have also same question :) why not make it to name with custom names.
I have got long running processes, let's say 2h to 1day. Each process starts its lifecycle with an update message and then continues to listen further concurrent updates. In the update message there is a unique target identifier.
If I want to represent each process with an Actor, how do I initialize the actor? I clearly need to do an atomic look-up/create operation based on the value of the identifier in the update message? How to do I design this with scala/akka?
Setup a single actor that performs the management of these process actors (say a ProcessManager actor). This actor will support requests to get a process actor for a particular process id. Internally, it will see if that child already exists or not. If it exists, it will respond to the sender with that ref. If not, it will create it and then respond to the sender with that ref. Because this manager actor processes it's mailbox serially (as all actors do), you don't have to worry about race conditions with the lookup/create. A very simplified example of this:
case class GetProcessHandler(processId:Int)
class ProcessManager extends Actor{
def receive = {
case GetProcessHandler(id) =>
val name = s"proc_$id"
val handler = context.child(name).getOrElse(
context.actorOf(Props[ProcessHandler], name)
)
sender ! handler
}
}
class ProcessHandler extends Actor{
def receive = {
...
}
}
You can specify your starting actors in your application.conf. And then your main program you can create/initialize these actors by using your ActorSystem.
I have a shared external resource (say a file store) which a pool of actors is using. Each time a new request is made to the file store a new actor is created to fill the request with a reference to the external system passed in.
The current approach where I create a circuit breaker per actor defeats the purpose as a new actor is created for each 'request' which performs a sequence of operations on this external resource.
Not ideal - too many CB instances;
class MySharedResourceActor(externalResourceRef: ExtSystem) extends Actor with ActorLogging {
val breaker = new CircuitBreaker(context.system.scheduler,
maxFailures = 5,
callTimeout = 10.seconds,
resetTimeout = 1.minute).onOpen(notifyMeOnOpen())
def receive = {
case SomeExternalOp =>
breaker.withSyncCircuitBreaker(dangerousCallToExternalSystem()) pipeTo sender()
}
}
Better Approach - pass in a CB ref;
class MySharedResourceActor(externalResourceRef: ExtSystem, val breaker: CircuitBreaker) extends Actor with ActorLogging {
def receive = {
case SomeExternalOp =>
breaker.withSyncCircuitBreaker(dangerousCallToExternalSystem()) pipeTo sender()
}
}
Is it safe to pass in a Circuit-breaker reference from the parent actor which also maintains a reference to the external system and share this circuit breaker between multiple actors in a router pool, dynamically created or otherwise?
Yes it's safe to follow this approach. We share circuit breakers across related actors (pooled or otherwise) that are making http calls to the same host. If you didn't do this, and let each instance have it's own breaker, even if they were long lived instances, each one would need to hit the fail threshold separately before the breaker opened and I doubt this is the behavior you want. By sharing, it allows multiple actors to contribute stats (fails, successes) into the breaker so that the breaker is representative of all calls that have gone into the resource.
In looking at Akka's code, they are using atomics inside of the circuit breaker to represent state and handle state transitions, so they should be safe to use in multiple actors.
I implement a REST service using Spray.io framework. Such service must receive some "search" queries, process them and send result back to the client(s). The code that perfrom searching located in separate actor - SearchActor, so after receiving (JSON) query from user, i re-send (using ask pattern) this query to my SearchActor. But what i don't really understand it's how i must implement interaction between spray.io route actor and my SearchActor.
I see here several variants but which one is more correct and why?
Create one instance of SearchActor at startup and send every request to this actor
For every request create new instance of SearchActor
Create pool of SearchActor actors at startup and send requests to this pool
You're not forced to use the ask pattern. In fact, it will create a thread for each of your request and this is probably not what you want. I would recommend that you use a tell instead. You do this by spawning a new Actor for each request (less expensive than a thread), that has the RequestContext in one of its constructor fields. You will use this context to give the response back, typically with its complete method.
Example code.
class RESTActor extends HttpService {
val route = path("mypath") ~ post {
entity(as[SearchActor.Search]) { search => ctx =>
SearchActor(ctx) ! search
}
}
}
case class SearchActor(ctx: RequestContext) {
def receive = {
case msg: Search => //... search process
case msg: Result => ctx.complete(msg) // sends back reply
}
}
Variant #1 is out of question after the initial implementation - you would want to scale out, so single blocking actor is bad.
Variants #2 and #3 are not very different - creation of new actor is cheap and has minimal overhead. As your actors may die often (i.e. backend is not available), i would say that #2 is the way to go.
Concrete implementation idea is shown at http://techblog.net-a-porter.com/2013/12/ask-tell-and-per-request-actors/
I'm trying to write server which listen for tcp connection.
I'm using nonblockig java.nio.
My selector.select() starts when actor receive "STARTLISTEN" message and it's ok, but when i sent messages to actor it not receive messages until selector not received any data.
How to avoid this? For example i want to send message "STOP" to my actor to stop selecting?
Is only way to call select with timeout or selectNow()?
I'm not going to use akka.io.
It's not full code but it illustrates the problem:
class MyActor(val host: String, port: Int) extends Actor {
val serverChannel = ServerSocketChannel.open()
val channelSelector = Selector.open()
serverChannel.configureBlocking(false);
serverChannel.bind(new InetSocketAddress( InetAddress.getByName(host), port ))
serverChannel.register(channelSelector, SelectionKey.OP_ACCEPT);
override def receive = {
case "STARTLISTEN" => {
val keys = channelSelector.select()
// processing read write etc....
}
case "STOP" => {
// I want to stop selection here....
}
}
}
Even though you dismiss it out of hand, I’d like to point out (on the record) that using the proven implementation of exactly this which ships with Akka already is probably the better way to go. (I’m linking to the 2.3.0-RC2 documentation because some of the experimental features which were introduced in the 2.2.x series will not be part of Akka going forward—survival of the fittest.)
You might be able to accomplish this by splitting your actor into multiple actors. The first actor receives messages from outside, and the second blocks on select(). The first actor can use wakeup() to stop the second from blocking before sending it any messages.