scala play: How to kill old actors / threads on automatic rebuild? - scala

I have a play application where I am using actors that are do some constant work / monitoring.
e.g.
class MyActor extends Actor {
def act() { while(true) { /* work */ } }
}
in my code I start this actor exactly once.
My problem is that whenever play automatically rebuilds the application (due to source changes), it will create a new Actor, but will not get rid of the old actor.
The exact same thing happens if using threads (including daemon threads) instead of actors for the monitoring.
Is there any way to kill the old actors / threads on an automatic rebuild, or alternatively ensure that only a single actor will exist (I've tried making the actor thread an object, but this didn't help anything), other than restarting the application manually (I'm fine automatically with restarting the application on every change)?
Also, is there a better pattern for background monitoring in play (obviously one which will not create non-ending threads).
Thanks

You can define a Global object to listen to application events (Which must be defined in the default package):
import play.api.GlobalSettings
object Global extends GlobalSettings {
override def onStart(application: play.api.Application) {
println("Starting actors")
MyActorSystem
}
override def onStop(application: play.api.Application) {
println("Stopping actors")
MyActorSystem.system.shutdown()
}
}
The stop and start events are triggered when reload happens.
If you are using Play's internal actor system I think you can use this instead:
play.api.libs.concurrent.Akka.system.shutdown()

Related

How to schedule complex tasks using Scala/Play 2.3?

I'm looking to schedule something to run once per day, and the code I want to run involves making updates to entries in the database. I have managed to schedule the running of some simple code by overriding the onStart method in Global.scala using Akka, as follows
override def onStart(app: Application) = {
Akka.system.scheduler.schedule(0.second, 1.second) {
println("hello!")
}
}
The issue is that I want to do something more complicated than logging here, I want to make updates to the database, so I would want to call some function in a models file (models/SomeTable.scala), but I can't import that code in Global.scala.
It sounds like if I want to do something more complicated like that, I should be using Akka's actor system, but I am far from understanding how that works. I've found documentation for how to create Actors through Akka's documentation, though how to incorporate that into my Play project is unclear. Where do I write this Actor class, and how is that imported (what is Global.scala allowed to have access to..?)? And if I don't need to use actors for this, does anyone have some insight into how imports and such work in this part of a Play project?
Note that this part of the Play framework underwent large changes going from Play version 2.3.* to 2.4.*, so it definitely should not be expected that solutions in 2.4.* would likely work here
The information I've gotten above has come mostly from Play's documentation, along with a bunch of related SO questions:
How to schedule task daily + onStart in Play 2.0.4?
how to write cron job in play framework 2.3
Scheduling delaying of jobs tasks in Play framework 2.x app
Where is the job support in Play 2.0?
Was asynchronous jobs removed from the Play framework? What is a better alternative?
Thanks so much in advance!
First of all you definitely need to read about akka.
But for your specific task you do not need to import anything into Global. You just need to start your worker actor. And this actor can schedule regular action itself. As Template
import akka.actor.{Actor, Cancellable, Props}
import scala.concurrent.duration._
class MyActor extends Actor {
private var cancellable: Option[Cancellable] = None
override def preStart(): Unit = {
super.preStart()
cancellable = Some(
context.system.scheduler.schedule(
1.second,
24.hours,
self,
MyActor.Tick
)(context.dispatcher)
)
}
override def postStop(): Unit = {
cancellable.foreach(_.cancel())
cancellable = None
super.postStop()
}
def receive: Receive = {
case MyActor.Tick =>
// here is the start point for your execution
// NEW CODE WILL BE HERE
}
}
object MyActor {
val Name = "my-actor"
def props = Props(new MyActor)
case object Tick
}
Here you have an actor class. With preStart and postStop (read more about actors lifecycle) where defined and cancelled schedule. Scheduled action is sending Tick message to self (in other words actor will receive each 24 hours Tick message and if receive is defined for Tick, this message will be processed).
So you just need to start you implementation where I placed comment.
From Global you just need to start this action in onStart:
Akka.system.actorOf(MyActor.props, MyActor.Name)

How to initialise a scala/akka Actor in an event driven architecture?

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.

Akka and Actor behavior interface

I just start trying myself out with Scala. I grow confident enough to start refactoring an ongoing multi-threaded application that i have been working on for about a year and half.
However something that somehow bother and i can't somehow figure it out, is how to expose the interface/contract/protocole of an Actor? In the OO mode, i have my public interface with synchronized method if necessary, and i know what i can do with that object. Now that i'm going to use actor, it seems that all of that won't be available anymore.
More specifically, I a KbService in my app with a set of method to work with that Kb. I want to make it an actor on its own. For that i need to make all the method private or protected given that now they will be only called by my received method. Hence the to expose the set of available behavior.
Is there some best practice for that ?
To tackle this issue I generally expose the set of messages that an Actor can receive via a "protocol" object.
class TestActor extends Actor {
def receive = {
case Action1 => ???
case Action2 => ???
}
}
object TestActorProtocol {
case object Action1
case object Action2
}
So when you want to communicate with TestActor you must send it a message from its protocol object.
import example.TestActorProtocol._
testActorRef ! TestActorProtocol.Action1
It can become heavy sometimes, but at least there is some kind of contract exposed.
Hope it helps

How to represent that an Akka actor is in a long running operation using FSM-s

My actor that is described with an FSM is waiting for a trigger (in Idle state). When it gets it it starts processing some data (and goes to Running state) and when it is done it goes back to Idle state.
If I understand the FSM model correctly, from this point of view there were two events:
processing started (Idle->Running) and processing completed (Running->Idle).
But from the actor point of view there was only one message.
One possibility is to delegate the processing itself to another actor. So I can forward the triggering event and go to Running state, then when got the result I go to Idle.
It has the advantage that the FSM itself can quickly react to requests (e.g. asking what's the current state), but it makes the design more complicated.
Another one is to send a completed message to self when the actor has completed processing, which will trigger the Running -> Idle transition, but it looks a bit strange for me.
What other options do I have?
Note: there are several other states with various transitions so I'd like to stick to the FSM model.
Since it seems like you have an actor that needs to do processing and make transitions to an FSM, I suggest you follow these guidelines (some basic code outline follows this list):
Actor A receives the message in question that will trigger some processing
Actor A transitions a separate FSM actor, say F, (akka.actor.FSM) to the appropriate state. Actor A on startup would spawn the specific FSM to track the state for the corresponding context (e.g. for all transactions or state per transaction or some other context). The code outline below uses all processing or completed transactions as the context for the example but may need to be changed.
Actor A then triggers whatever processing should be triggered for the message. Remember actors shouldn't block generally, but here is an answer that provides more guidelines on when an Akka actor may block.
Alternative: If you can trigger long running processing without blocking and ensure you receive the necessary events after processing stages by the other party, then you could eliminate the front Actor A and just have the FSM actor F. You should look at onTransition in this case.
So my code outline suggestion is based on what I understood from the question is:
/* Events */
sealed trait MyEvents
case class ProcessingStarted(txnId: Long) extends MyEvents
case class ProcessingFinished(txnId: Long, result: Result) extends MyEvents
/* Valid states for your FSM */
sealed trait MyStates
case object Idle extends MyStates
/* Constructor arguments could be anything, I randomly chose a Long for a transaction ID which may be specific to a job */
case object Processing extends MyStates
/* define more case classes or objects depending on the rest of the states */
/* Valid internal state data types for FSM */
sealed trait MyDataTypes
case object Uninitialized extends MyDataTypes
case class StateData(processingIds: Seq[Long], resultMap: Map[Long, Result]) extends MyDataTypes
import akka.actor.{ Actor, ActorRef, FSM }
import scala.concurrent.duration._
class ActorF extends FSM[MyStates, MyDataTypes] {
startWith(Idle, Uninitialized)
when(Idle) {
case Event(ProcessingStarted(txnId), Uninitialized) =>
goto(Processing) using StateData(Seq(txnId), Map.empty[Long, Result])
case Event(ProcessingStarted(txnId), StateData(emptyIds, resultMap)) =>
goto(Processing) using StateData(Seq(txnId), resultMap)
}
when(Processing) {
case Event(ProcessingFinished(txnId, result), StateData(processingIds, resultMap)) => {
val remainingIds = processingIds diff Seq(txnId)
val newResultMap = resultMap + (txnId -> result)
if (remainingIds.isEmpty) {
goto(Idle) using StateData(remainingIds, newResultMap)
} else {
stay using StateData(remainingIds, newResultMap)
}
}
}
initialize()
}
// inside Actor A do something like this for creating the FSM actor (just like other actors)
val f = system.actorOf(Props(classOf[ActorF], this))
// send an event message to it just like other types of actors
f ! ProcessingStarted(txnId)
If you choose to trigger off non-blocking processing requests to other parts of your code you can use onTransition to add the trigger code in as necessary. You may also want to update the MyEvents case classes to a different tense. The event naming was used above was to show that something else was responsible for triggering that off (e.g. Actor A the received the initial message to do some things).
Also take note of Supervision capabilities of Akka which could be used here to supervise the actors in question.
For more details read the following which might help further with building your FSM, testing it, using non-blocking methods to trigger long-running processing externally. All of which might be useful for your needs:
Scala docs for Akka 2.2.x: FSMs
Scala docs for Akka 2.2.x: Testing
Scala docs for Akka 2.2.x: Akka IO for non-blocking
Scala docs for Akka 2.2.x: ZeroMQ

Creating custom Akka Supervisor that shuts down all linked actors

This earlier question suggests that calling 'stop' on a supervisor actor will shut down all linked actors. However, if one creates a 'custom' actor (not through a factory), it seems that this auto-shutdown doesn't happen. For example, see this code from the answer to another question:
class Module1 extends Actor {
self.faultHandler = OneForOneStrategy(List(classOf[Throwable]), 5, 5000)
def receive = {
case Register(actor) =>
self.link(actor)
}
}
If 'stop' was called on the above Module1 actor, the actors linked to it wouldn't shut down. Is there a way to make a custom actor automatically shut down linked actors? Or is this just something that you have to write yourself if you want to create a custom actor?
Thanks!
You can call:
self.linkedActors.values.iterator
and then send a PoisonPill or stop() them.