Shutting down an Akka Actor system from an Actor - scala

I know I can use system.shutdown() outside of an actor system to stop the actor system and make system.awaitTermination() stop blocking execution on its thread.
I want to trigger the actor system shutdown from within one of my Actors. I thought I should be able to call context.system.shutdown() from within an Actor's receive method, however when I do this nothing seems to happen, system.awaitTermination() (on the main thread) just keeps on blocking.
Any ideas?

How to program an Actor to kill self
class WatchActor extends Actor {
val child = context.actorOf(Props.empty, "child")
context.watch(child) // <-- this is the only call needed for registration
var lastSender = system.deadLetters
def receive = {
case "kill" =>
context.stop(child); lastSender = sender()
case Terminated(`child`) => lastSender ! "finished"
}
}
At this url there is a good explain.
http://doc.akka.io/docs/akka/snapshot/scala/actors.html
jfm

You should not do that: it is like a snake biting its own tail.
system.awaitTermination() will keep blocking because you are precisely waiting for it to end!
You can perfectly call context.system.shutdown() within an actor, but you cannot call system.awaitTermination() in the actor system context. And also it does not make a lot of sense: why would you wait since there is anyway nothing to execute afterwards, the system being down?
Blocking on the system to shut down makes sense outside of it only, if you want to execute further instructions after it has been stopped.

Main Thread:
val l = new CountDownLatch(1)
val s = ActorSystem("system", config)
...
//create some actors and send some messages to them
...
l.await()
s.shutdown()
s.awaitTermination()
Some where in def receive: Actor.Receive:
l.countDown()

Related

ExecutionContext causes Akka dead letter

For some reason I have to use gRPC and Akka at the same time. When this actor is started as a top actor, nothing goes wrong (in this little demo). But when it becomes a child actor, it cannot receive any messages, and the following is logged:
[default-akka.actor.default-dispatcher-6] [akka://default/user/Grpc] Message [AkkaMessage.package$GlobalStart] from Actor[akka://default/user/TrackerCore#-808631363] to Actor[akka://default/user/Grpc#-1834173068] was not delivered. [1] dead letters encountered.
The example core:
class GrpcActor() extends Actor {
val ec = scala.concurrent.ExecutionContext.global
val service = grpcService.bindService(new GrpcServerImpl(), ec)
override def receive: Receive = {
case GlobalStart() => {
println("GlobalStart")
}
...
}
}
I tried to create a new ExecutionContext like:
scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(10))
Why is this happening, and how do can I debug a dead letters problem like this (no exception is thrown)?
Update:
Sorry I didn't list everything here. I used normal Main method to test GrpcActor as top actor, and ScalaTest to test it as child actor, which is a mistake.
class GrpcActorTest extends FlatSpec with Matchers{
implicit val system = ActorSystem()
val actor: ActorRef = system.actorOf(Props[GrpcActor])
actor ! GlobalStart()
}
It is this empty test suite that active shutdown the whole actor system. But the problem is with this line
val service = grpcService.bindService(new GrpcServerImpl(), ec)
the delivery of GlobalStart() was delayed after the shutdown.
Without that line, message can be delivered before the shutdown.
Is this a normal behavior?
(My guess: it happened that the GlobalStart() was queued after the shutdown message with that line, which did some heavy work and made the difference in time)
One way to address the problem is to make service a lazy val:
class GrpcActor extends Actor {
...
lazy val service = grpcService.bindService(new GrpcServerImpl(), ec)
...
}
A lazy val is useful for long-running operations: in this case, it defers the initialization of service until it is used for the first time. Without the lazy modifier, service is initialized when the actor is created.
An alternative approach is to add a Thread.sleep in your test to prevent the actor system from shutting down before the actor has fully initialized:
class GrpcActorTest extends FlatSpec with Matchers {
...
actor ! GlobalStart()
Thread.sleep(5000) // or whatever length of time is needed to initialize the actor
}
(As a side note, consider using the Akka Testkit for your actor tests.)
Add a supervisor strategy to its parent, add println to the actor lifecycle. There is something that kill your actor . Finally, if you provide a complete example maybe I can say more :)

What is the purpose of the Terminated message

import akka.actor.{ Actor, Props, Terminated }
class WatchActor extends Actor {
val child = context.actorOf(Props.empty, "child")
context.watch(child) // <-- this is the only call needed for registration
var lastSender = context.system.deadLetters
def receive = {
case "kill" =>
context.stop(child); lastSender = sender()
case Terminated(`child`) => lastSender ! "finished"
}
}
I am getting confused here regarding the Terminated message.
When an actor creates a child actor, isn't it by default watching it already?
And if that child actor dies prematurely, the default strategy would be to restart it correct?
What is the purpose of the Terminated message in the above code snippet? (taken from the akka website: http://doc.akka.io/docs/akka/2.4/scala/actors.html)
If the child actor terminates, the WatchActor will get that message? But it is sending the lastSender() the "finished" message, and the lastSender is the child actor in this case is it not?
The purpose is to get notification from child actor when it dies.
Talking about example in Akka docs, lastSender is the actor that have sent a message to the watchActor:
lastSender ----"kill"---> watchActor ---context.stop---> child
<--"finished-- <--Terminated------
So, lastSender is an actor that have sent the "kill" message (string) to delegate the killing process. It's not the same as child, and not the same as watchActor
Another catch is that intermediate WatchActor (kind of "Hitman", not just monitor) might not create a child originally, so that's why it has to subscribe to lifecycle of actor named as "child", as you can see from that example:
val child = context.actorOf(Props.empty, "child")
context.watch(child)
P.S. if you ask me about purpose of such complex protocol, my guess is that it's OOP-like single responsibility. However, IMO, I never liked that akka is distorting original actor's concept (IO-protocol and state handling) with lifecycle stuff. However, this is what you get with Akka - it's kinda simpler with streaming libraries (akka-streams, fs2, monix), so you might try them if it fits your purpose.

Puzzled by the spawned actor from a Spray route

I am doing some Http request processing using Spray. For a request I spin up an actor and send the payload to the actor for processing and after the actor is done working on the payload, I call context.stop(self) on the actor to wind the actor down.The idea is to prevent oversaturation of actors on the physical machine.
This is how I have things set up..
In httphandler.scala, I have the route set up as follows:
path("users"){
get{
requestContext => {
val userWorker = actorRefFactory.actorOf(Props(new UserWorker(userservice,requestContext)))
userWorker ! getusers //get user is a case object
}
}
} ~ path("users"){
post{
entity(as[UserInfo]){
requestContext => {
userInfo => {
val userWorker = actorRefFactory.actorOf(Props(new UserWorker(userservice,requestContext)))
userWorker ! userInfo
}
}
}
}
}
My UserWorker actor is defined as follows:
trait RouteServiceActor extends Actor{
implicit val system = context.system
import system.dispatcher
def processRequest[responseModel:ToResponseMarshaller](requestContex:RequestContext)(processFunc: => responseModel):Unit = {
Future{
processFunc
} onComplete {
case Success(result) => {
requestContext.complete(result)
}
case Failure(error) => requestContext.complete(error)
}
}
}
class UserWorker(userservice: UserServiceComponent#UserService,requestContext:RequestContext) extends RouteServiceActor{
def receive = {
case getusers => processRequest(requestContext){
userservice.getAllUsers
}
context.stop(self)
}
case userInfo:UserInfo => {
processRequest(requestContext){
userservice.createUser(userInfo)
}
context.stop(self)
}
}
My first question is, am I handling the request in a true asynchronous fashion? What are some of the pitfalls with my code?
My second question is how does the requestContext.complete work? Since the original request processing thread is no longer there, how does the requestContext send the result of the computation back to the client.
My third question is that since I am calling context.stop(self) after each of my partial methods, is it possible that I terminate the worker while it is in the midst of processing a different message.
What I mean is that while the Actor receives a message to process getusers, the same actor is done processing UserInfo and terminates the Actor before it can get to the "getusers" message. I am creating new actors upon every request, but is it possible that under the covers, the actorRefFactory provides a reference to a previously created actor, instead of a new one?
I am pretty confused by all the abstractions and it would be great if somebody could break it down for me.
Thanks
1) Is the request handled asynchronously? Yes, it is. However, you don't gain much with your per-request actors if you immediately delegate the actual processing to a future. In this simple case a cleaner way would be to write your route just as
path("users") {
get {
complete(getUsers())
}
}
def getUsers(): Future[Users] = // ... invoke userservice
Per-request-actors make more sense if you also want to make route-processing logic run in parallel or if handling the request has more complex requirements, e.g. if you need to query things from multiple service in parallel or need to keep per-request state while some background services are processing the request. See https://github.com/NET-A-PORTER/spray-actor-per-request for some information about this general topic.
2) How does requestContext.complete work? Behind the scenes it sends the HTTP response to the spray-can HTTP connection actor as a normal actor message "tell". So, basically the RequestContext just wraps an ActorRef to the HTTP connection which is safe to use concurrently.
3) Is it possible that "the worker" is terminated by context.stop(self)? I think there's some confusion about how things are scheduled behind the scenes. Of course, you are terminating the actor with context.stop but that just stops the actor but not any threads (as threads are managed completely independently from actor instances in Akka). As you didn't really make use of an actor's advantages, i.e. encapsulating and synchronizing access to mutable state, everything should work (but as said in 1) is needlessly complex for this use case). The akka documentation has lots of information about how actors, futures, dispatchers, and ExecutionContexts work together to make everything work.
In addition to jrudolph answer your spray routing structure shouldn't even compile, cause in your post branch you don't explicitly specify a requestContext. This structure can be simplified a bit to this:
def spawnWorker(implicit ctx: RequestContext): ActorRef = {
actorRefFactory actorOf Props(new UserWorker(userservice, ctx))
}
lazy val route: Route = {
path("users") { implicit ctx =>
get {
spawnWorker ! getUsers
} ~
(post & entity(as[UserInfo])) {
info => spawnWorker ! info
}
}
}
The line info => spawnWorker ! info can be also simplified to spawnWorker ! _.
Also there is an important point concerning explicit ctx declaration and complete directive. If you explicitly declared ctx in your route, you can't use complete directive, you have to explicitly write ctx.complete(...), link on this issue

How to check scala actors status from main process?

I am relatively new Scala actors. I have huge map,that is grouped into smaller blocks and executed through actors. Based on map size,the number of actors created vary. The actors work well and the process is completed. But how to check the status of the generated actors? In java i am familiar with use of thread-pool executor services. In Scala how this is done?
There are multiple ways to do what you want:
Have the worker actor send a message back to the sender to inform it that an operation completed. Each actor has a reference to the sender actor (the one that sent the message), which you can use to send back a completion message. The sender can then handle that message.
Instead of sending a message via a tell (e.g. actor ! msg), use ask, which returns a Future. You can setup a callback on the Future that runs upon completion.
If the worker actors are launched for a one-time operation, have it terminate itself by stopping it once the operation finishes. The parent actor (the one which created the worker actor) can monitor the worker via a DeathWatch mechanism that informs the parent when the child actor is terminated. In this approach, termination means the operation has been completed. However, you will need to keep track of how many terminations the parent receives in order to determine when all the worker actors have finished.
Which approach to use depends on your use case and nature of the operations. Most common and flexible approach is #1. Example (not tested):
case class PerformWork(i: Int)
case object WorkDone
class ParentActor(size: Int) extends Actor {
for (i <- 1 to size) {
val actor = context.actorOf(Props[Worker], s"worker$i")
actor ! PerformWork(i)
}
var result = 0
def receive = {
case WorkDone => {
result += 1
if (result == size) {
// work is done
}
}
}
}
class Worker extends Actor {
def receive = {
case m: PerformWork => {
// do some work
// ...
sender ! WorkDone
}
}
}

Calling an blocking Actor from within an Actor

Given I invoke an Actor from inside react does this block the calling Actor or is it still processing other requests?
class worker extends Actor()
{
def act() = {
loop {
react {
msg =>
var foo = another_actor !? 'bar' //Block here?
println(foo)
}
}
}
!? always blocks the calling thread. if it is invoke in middle of actor react block, the calling actor is blocked as well.
The main idea of actors is a single thread of execution. An actor will not proceed to the next message until the current one is finished processing. this way, the developers do not need to worry about concurrency as long as the messages are immuatable.
See this question about the fact that actors cannot process messages simulatneously (i.e. each actor processes its inbox sequentially).
I certainly don't think that this is very clear from the explanations in Programming in Scala. You can (sort of) achieve what you want by creating an on-the-fly actor:
loop {
react {
case Command(args) =>
val f = other !! Request(args) //create a Future
//now create inline actor
val _this = self
actor { //this creates an on-the-fly actor
_this ! Result(args, f.get) //f.get is a blocking call
}
case Result(args, result) =>
//now process this
}
}
Of course, the on-the-fly actor will block, but it does leave your original actor able to process new messages. The actors subsystem will create new threads up to actors.maxPoolSize (default is 256) if all current pooled worker threads are busy.