schedule and cancel an unknown number of message sendings - scala

I want an Actor to be able to scheduleOnce() a message sending - any number of times - through message receipt (receive()). The cancellable thus created can be cancel()led through message receipt.
I encounter great difficulties to think about an architecture to handle this. Anyone'd have a clue on how to build this, with multiple Actors, functions, etc...?
Can I just cancel() the id defined as follows?
class myActor extends Actor {
def Receive = {
case msg(t) => {
createTrigger(t)
}
case _ => //do something
}
def createTrigger(t) => {
val id/*cancellable*/ = context.system.scheduler.schedule(t milliseconds,
someActor,
someMessage)
}
def cancelSchedule(cancellable) => {
cancellable.cancel()
}
}

Related

Akka actor system with HTTP interface

I'm trying to create an Akka system which would among other things respond to HTTP requests. I created a few actors who exchange messages fine. I can also use akka-http to respond to HTTP requests. The problem is in connecting those two parts.
TL;DR: How to talk to Akka actors during akka-http request processing?
I created a single actor responsible for bringing up the HTTP system:
class HttpActor extends Actor with ActorLogging {
/* implicits elided */
private def initHttp() = {
val route: Route = path("status") { get { complete { "OK" } } }
Http()(context.system).bindAndHandle(route, "localhost", 8080)
}
private var bound: Option[Future[Http.ServerBinding]] = None
override def receive = {
case HttpActor.Init =>
bound match {
case Some(x) => log.warning("Http already bootstrapping")
case None =>
bound = Some(initHttp(watcher))
}
}
}
object HttpActor {
case object Init
}
As you may see, the actor creates the akka-http service on the first message it receives (no reason, really, it could do it in the constructor as well).
Now, during the request processing I need to communicate with some other actors, and I can't get it working.
My approach:
private def initInteractiveHttp() = {
val route: Route = path("status") {
get { complete { "OK" } }
} ~ path("ask") {
get { complete {
// Here are the interesting two lines:
val otherActorResponse = someOtherActor ? SomeMessage
otherActorResponse.mapTo[String]
} }
Http()(context.system).bindAndHandle(route, "localhost", 8080)
}
This would send a SomeMessage to someOtherActor and wait for response prior to completing the Request-Response cycle. As I understand, however, that messages would be sent from the root HttpActor, which is bad and leads nowhere in terms of scalability. Ideally I would create a distinct instance of specialized actor for every request, but this fails due to akka-http typing. Consider the following example:
class DisposableActor(httpContext: HttpContext) {
override def preStart() = {
// ... send some questions to other actors
}
override def receive = {
case GotAllData(x) => httpContext.complete(x)
}
}
class HttpActorWithDisposables {
// there is a `context` value in scope - we're an actor, after all
private def initHttpWithDisposableActors() = {
val route: Route = path("status") {
get { complete { "OK" } }
} ~ path("ask") {
get { httpContext =>
val props = Props(new DisposableActor(httpContext))
val disposableActor = context.actorOf(props, "disposable-actor-name")
// I have nothing to return here
}
}
Http()(context.system).bindAndHandle(route, "localhost", 8080)
}
With this approach, I can force the DisposableActor to call httpContext.complete at some point of time. This should correctly end the Request-Response processing cycle. The Route DSL, however, requires to return a valid response (or Future) inside the get block, so this approach doesn't work.
Your first approach is quite alright, actually.
The ask pattern creates a lightweight, disposable actor for you that waits on the result (non-blockingly) to complete the future. It basically does all the things you want to replicate with the DisposableActor and your main HttpActor is not stressed by this.
If you still want to use a different actor, there is completeWith:
completeWith(instanceOf[String]) { complete =>
// complete is of type String => Unit
val props = Props(new DisposableActor(complete))
val disposableActor = context.actorOf(props, "disposable-actor-name")
// completeWith expects you to return unit
}
And in you actor, call the complete function when you have the result
class DisposableActor(complete: String => Unit) {
override def receive = {
case GotAllData(x) =>
complete(x)
context stop self // don't for get to stop the actor
}
}

Accessing states of an Akka Actor through messages

I'm trying to access the state of a particular actor through messaging. What I don't know is how I can retrieve the state of the actor. Here, I need to access the state variable of Node, state1. I want to avoid using promises/futures in the code. How should I go about modifying this code if I want to do that?
class Node extends Actor {
val state1:Int = 4
def receive = {
case getState => {
sender ! ??? //How should I send the 'state1' to the sender?
}
}
}
class Master extends Actor {
def recieve = {
case someCase(node_actor:ActorRef) => {
// My aim here is to get the "state1" from node actor into var 's'
var s:Int = node_actor ! getState
}
}
}
Actors are designed perfectly to avoid manual handling of scala.concurrent. things.
Just separate request and response handling into different receive cases:
class Node extends Actor {
import Node._
val state1: Int = 4
def receive: Receive = {
case getState =>
sender ! State(state1)
}
}
class Master extends Actor {
import Master._
def receive: Receive = {
case Action(node) =>
// My aim here is to get the "state1" from node actor into var 's'
node ! Node.GetState
case Node.State(state) =>
// do something with state
}
}
object Master {
case class Action(node: ActorRef)
}
object Node {
case object GetState
case class State(state: Int)
}
Sometimes you could have also some intermediate values calculated and don't want to do something until you'll get the answer but being unreachable also is not acceptable. So you could just wait for node response in separate Receive while stashing incoming messages, like this:
class Master extends Actor with Stash {
import Master._
def receive: Receive = {
case Action(node) =>
val intermediate = scala.util.Random.nextLong()
node ! Node.GetState
context.become(waitingForState(calc = intermediate), discardOld = false)
}
def waitingForState(calc: Long): Receive = {
case Node.State(state) =>
// do something with state and calc
context.unbecome()
unstashAll()
case _ => stash()
}
}

Initializing an actor before being able to handle some other messages

I have an actor which creates another one:
class MyActor1 extends Actor {
val a2 = system actorOf Props(new MyActor(123))
}
The second actor must initialize (bootstrap) itself once it created and only after that it must be able to do other job.
class MyActor2(a: Int) extends Actor {
//initialized (bootstrapped) itself, potentially a long operation
//how?
val initValue = // get from a server
//handle incoming messages
def receive = {
case "job1" => // do some job but after it's initialized (bootstrapped) itself
}
}
So the very first thing MyActor2 must do is do some job of initializing itself. It might take some time because it's request to a server. Only after it finishes successfully, it must become able to handle incoming messages through receive. Before that - it must not do that.
Of course, a request to a server must be asynchronous (preferably, using Future, not async, await or other high level stuff like AsyncHttpClient). I know how to use Future, it's not a problem, though.
How do I ensure that?
p.s. My guess is that it must send a message to itself first.
You could use become method to change actor's behavior after initialization:
class MyActor2(a: Int) extends Actor {
server ! GetInitializationData
def initialize(d: InitializationData) = ???
//handle incoming messages
val initialized: Receive = {
case "job1" => // do some job but after it's initialized (bootstrapped) itself
}
def receive = {
case d # InitializationData =>
initialize(d)
context become initialized
}
}
Note that such actor will drop all messages before initialization. You'll have to preserve these messages manually, for instance using Stash:
class MyActor2(a: Int) extends Actor with Stash {
...
def receive = {
case d # InitializationData =>
initialize(d)
unstashAll()
context become initialized
case _ => stash()
}
}
If you don't want to use var for initialization you could create initialized behavior using InitializationData like this:
class MyActor2(a: Int) extends Actor {
server ! GetInitializationData
//handle incoming messages
def initialized(intValue: Int, strValue: String): Receive = {
case "job1" => // use `intValue` and `strValue` here
}
def receive = {
case InitializationData(intValue, strValue) =>
context become initialized(intValue, strValue)
}
}
I don't know wether the proposed solution is a good idea. It seems awkward to me to send a Initialization message. Actors have a lifecycle and offer some hooks. When you have a look at the API, you will discover the prestart hook.
Therefore i propose the following:
When the actor is created, its preStart hook is run, where you do your server request which returns a future.
While the future is not completed all incoming messages are stashed.
When the future completes it uses context.become to use your real/normal receive method.
After the become you unstash everything.
Here is a rough sketch of the code (bad solution, see real solution below):
class MyActor2(a: Int) extends Actor with Stash{
def preStart = {
val future = // do your necessary server request (should return a future)
future onSuccess {
context.become(normalReceive)
unstash()
}
}
def receive = initialReceive
def initialReceive = {
case _ => stash()
}
def normalReceive = {
// your normal Receive Logic
}
}
UPDATE: Improved solution according to Senias feedback
class MyActor2(a: Int) extends Actor with Stash{
def preStart = {
val future = // do your necessary server request (should return a future)
future onSuccess {
self ! InitializationDone
}
}
def receive = initialReceive
def initialReceive = {
case InitializationDone =>
context.become(normalReceive)
unstash()
case _ => stash()
}
def normalReceive = {
// your normal Receive Logic
}
case class InitializationDone
}

Is it possible to use 'react' to wait for a number of child actors to complete, then continue afterwards?

I'm getting all in a twist trying to get this to work. New to scala and to actors so may inadvertently be making bad design decisions - please tell me if so.
The setup is this:
I have a controlling actor which contains a number of worker actors. Each worker represents a calculation that for a given input will spit out 1..n outputs. The controller has to set off each worker, collect the returned outputs, then carry on and do a bunch more stuff once this is complete. This is how I approached it using receive in the controller actor:
class WorkerActor extends Actor {
def act() {
loop {
react {
case DoJob =>
for (1 to n) sender ! Result
sender ! Done
}
}
}
}
The worker actor is simple enough - it spits out results until it's done, when it sends back a Done message.
class ControllerActor(val workers: List[WorkerActor]) extends Actor {
def act() {
workers.foreach(w => w ! DoJob)
receiveResults(workers.size)
//do a bunch of other stuff
}
def receiveResults(count: Int) {
if (count == 0) return
receive {
case Result =>
// do something with this result (that updates own mutable state)
receiveResults(count)
case Done
receiveResults(count - 1)
}
}
}
The controller actor kicks off each of the workers, then recursively calls receive until it has received a Done message for each of the workers.
This works, but I need to create lots of the controller actors, so receive is too heavyweight - I need to replace it with react.
However, when I use react, the behind-the-scenes exception kicks in once the final Done message is processed, and the controller actor's act method is short-circuited, so none of the "//do a bunch of other stuff" that comes after happens.
I can make something happen after the final Done message by using andThen { } - but I actually need to do several sets of calculations in this manner so would end up with a ridiculously nested structure of andThen { andThen { andThen } }s.
I also want to hide away this complexity in a method, which would then be moved into a separate trait, such that a controller actor with a number of lists of worker actors can just be something like this:
class ControllerActor extends Actor with CalculatingTrait {
//CalculatingTrait has performCalculations method
val listOne: List[WorkerActor]
val ListTwo: List[WorkerActor]
def act {
performCalculations(listOne)
performCalculations(listTwo)
}
}
So is there any way to stop the short-circuiting of the act method in the performCalculations method? Is there a better design approach I could be taking?
You can avoid react/receive entirely by using Akka actor's. Here's what you implementation could look like:
import akka.actor._
class WorkerActor extends Actor {
def receive = {
case DoJob =>
for (_ <- 1 to n) sender ! Result
sender ! Done
}
}
class ControllerActor(workers: List[ActorRef]) extends Actor {
private[this] var countdown = workers.size
override def preStart() {
workers.foreach(_ ! DoJob)
}
def receive = {
case Result =>
// do something with this result
case Done =>
countdown -= 1
if (countdown == 0) {
// do a bunch of other stuff
// It looks like your controllers die when the workers
// are done, so I'll do the same.
self ! PoisonPill
}
}
}
Here's how I might approach it (in way that seems to be more comments and boilerplate than actual content):
class WorkerController(val workerCriteria: List[WorkerCriteria]) {
// The actors that only _I_ interact with are probably no one else's business
// Your call, though
val workers = generateWorkers(workerCriteria)
// No need for an `act` method--no need for this to even be an actor
/* Will send `DoJob` to each actor, expecting a reply from each.
* Could also use the `!!` operator (instead of `!?`) if you wanted
* them to return futures (so WorkerController could continue doing other
* things while the results compute). The futures could then be evaluated
* with `results map (_())`, which will _then_ halt execution to wait for each
* future that isn't already computed (if any).
*/
val results = workers map (_ !? DoJob)
//do a bunch of other stuff with your results
def generateWorkers(criteria: List[WorkerCriteria]) = // Create some workers!
}
class Worker extends Actor {
def act() {
loop {
react {
case DoJob =>
// Will generate a result and send it back to the caller
reply(generateResult)
}
}
}
def generateResult = // Result?
}
EDIT: Have just been reading about Akka actors and spotted that they "guarantee message order on a per sender basis". So I updated my example such that, if the controller needed to later ask the receiver for the computed value and needed to be sure it was all complete, it could do so with a message order guarantee on only a per sender basis (the example is still scala actors, not akka).
It finally hit me, with a bit of help from #Destin's answer, that I could make it a lot simpler by separating out the part of the controller responsible for kicking off the workers from the part responsible for accepting and using the results. Single responsibility principle I suppose... Here's what I did (separating out the original controlling actor into a controlling class and a 'receiver' actor):
case class DoJob(receiever: Actor)
case object Result
case object JobComplete
case object Acknowledged
case object Done
class Worker extends Actor {
def act {
loop {
react {
case DoJob(receiver) =>
receiver ! Result
receiver ! Result
receiver !? JobComplete match {
case Acknowledged =>
sender ! Done
}
}
}
}
}
class Receiver extends Actor {
def act {
loop {
react {
case Result => println("Got result!")
case JobComplete => sender ! Acknowledged
}
}
}
}
class Controller {
val receiver = new Receiver
val workers = List(new Worker, new Worker, new Worker)
receiver.start()
workers.foreach(_.start())
workers.map(_ !! DoJob(receiver)).map(_())
println("All the jobs have been done")
}

how to correctly setup Akka.Actors compared to Scala.Actors

How do I run 2 Akka actors with the caller sending the consumer a message every n seconds?
As there are no loop-react methods as in the Scala.Actors library I am stuck
somehow, the following will not compile and produces:
overriding method receive in trait Actor of type =>
Caller.this.Receive; method receive has incompatible type
object Foo {
def init() {
actorOf[Caller].start()
actorOf[Consumer].start()
}
}
class Caller extends Actor {
def receive {
while (true) {
self ! "msg"
Thread.sleep(1000)
}
}
}
class Consumer extends Actor {
def receive = {
case msg:String => doStuff()
case e => _
}
}
You're missing the equals sign after receive in Caller. Without it, the method is defined as returning Unit (i.e. no useful value), and akka needs you to return a PartialFunction[Any,Unit] from receive.
Now, to actually implement your logic in the idiomatic way, you probably want to use a ReceiveTimeout, like so:
class Caller extends Actor {
self.receiveTimeout = Some(1000)
def receive = {
case ReceiveTimeout =>
self ! "msg"
}
}