How can I join started Actor? - scala

After starting an actor
val a = actor {
loop {
react {
case "end" => exit
...
}
}
}
And sending "end" message to it
a ! "end"
I want to make sure the thread is finished.
How can it be joined?

As far as I know an actor can't be joined explicitly as in the Java-way. The concept is to introduce event-based programming, so it should only react on events.
You can trap the exit however and link your initial actor (A) to the ending actor (B) via link. That way the initial actor A receives an event when B ends. If you don't get any event you know the actor hasn't terminated. See the thread here: https://stackoverflow.com/a/4304602/999865
If you don't care about resources and knows that the thread will terminate you can also make the actor inherit from DaemonActor. Daemon actors doesn't block any system resources.

Seems to me that the "actor-way" of doing what you want is actually have your actor reply with a message "Done" to the requester, so it can take action. That way it is all still asynchronous event handling

Related

How to supervise a typed actor that has a scheduler and register itself using receptionist?

The following is how I create a behavior:
Behaviors.setup(ctx => {
ctx.system.receptionist ! Receptionist.Register(serviceKey, ctx.self)
Behaviors.withTimers[Request](scheduler => {
ctx.self ! Msg1 // Not sure if this is related to this question
scheduler.startTimerWithFixedDelay(Msg2, 1.hour)
new MyExtensionOfAbstractBehavior(ctx,scheduler)
})
})
Now I would like to add supervision. To keep it simple I want SupervisorStrategy.resume or SupervisorStrategy.restart. But I don't know how to add that supervision. I know the following code will compile. But I am not sure that is the right approach.
Behaviors.supervise[Request]( ... every thing in the previous code ...)
.onFailure(SupervisorStrategy.resume)
When an actor restarts or resumes its behavior, it won't get deregistered in receptionist (is that true?). So I should not re-register the actor every time it restarts or resumes its behavior.
I have a similar problem with the scheduler. I don't know if I have to make sure Behaviors.withTimers gets re-executed or not upon restart/ resume.
On restart or resumption, the actor is, to the outside world, still the same actor, so I probably wouldn't wrap receptionist registration with supervise. As for the timers, I think the question is whether you want to reset the timers: if you do, then wrap withTimers in supervise.

When to use Ask pattern in Akka

I'm started to learn Akka and in many official examples I see that request-response implemented using tell pattern. I.e. after worker made his work he sends result as new message back to sender. For example in this Pi approximation official tutorial shown how to design application where Master sends some work to workers and then awaits for results as another message.
Master code:
def receive = {
case Calculate ⇒
for (i ← 0 until nrOfMessages) workerRouter ! Work(i * nrOfElements, nrOfElements)
case Result(value) ⇒
pi += value
nrOfResults += 1
if (nrOfResults == nrOfMessages) {
// Send the result to the listener
listener ! PiApproximation(pi, duration = (System.currentTimeMillis - start).millis)
// Stops this actor and all its supervised children
context.stop(self)
}
}
Worker code:
def receive = {
case Work(start, nrOfElements) ⇒
sender ! Result(calculatePiFor(start, nrOfElements)) // perform the work
}
But I'm wondering why this example didn't use ask pattern? What is wrong with using ask pattern here?
If it's ok to use ask pattern here, then I have another question: how I can stop all worker actors after work is done?
Should my worker actors send PoisonPill message to themselves?
Or should Master actor Broadcast(PoisonPill)?
Or there some another more elegant way?
ask is useful when integrating actors with Future APIs, but they do introduce some overhead. Further, Future completions do not come through an actor's mailbox and are scheduled on a thread separate from the one used by the mailbox, meaning that receiving a future completion inside an actor introduces the need for doing multi-thread coordination.
Meanwhile, if you use tell to send to a worker and have it tell the sender in response, the communication will always flow properly through the mailbox channel.
Additionally, it is much easier to discern the inputs an actor deals with if they all come in via receive rather than some coming in via receive and other's as completions of ask messages.
To address you PoisonPill questions, the answer is likely depends. You might opt for a worker-per-message approach in which case the worker should kill itself. If instead you use a worker pool, you could make the supervisor responsible for scaling that pool up and down, having it send the PoisonPill or have workers time out on idleness, once again killing themselves.

Check if a Scala / Akka actor is terminated

While executing code within one actor, I need to check if the actor is still alive.
Would this be advisable or is there a better way?
if (self != akka.actor.DeadLetter) {
// do something
}
Thanks!
EDIT---
Thanks for all your inputs. What happens is the following. I am using Play. As my actor starts, upon an incoming request, a timeout is scheduled.
Promise.timeout({
Logger.info(s"$self, timeout expired")
// do something
}, timeoutValue)
Sometimes the actor is stopped for other reasons before the timeout expires (for instance, the client disconnects). In that case, what I see then in the logs is
Actor[akka://application/deadLetters], timeout expired.
To my understanding, this means that the default deadLetters actor is executing that code. So my question really is: what is the best way to check if the Promise code is executed after the actor is terminated, and prevent it from going further if that is the case?
You should familiarize yourself with the actor lifecycle: http://doc.akka.io/docs/akka/2.3.4/scala/actors.html#Actor_Lifecycle
From inside an actor you can implement the postStop() callback that will be called immediately before your actor is going to be stopped. If you want to monitor the lifecycle of the actor from another actor you should use DeathWatch: http://doc.akka.io/docs/akka/2.3.4/scala/actors.html#Lifecycle_Monitoring_aka_DeathWatch
If your actor is dead, no code within the actor will be running.
You can check if specific actor is available, with actorSelection, and then send a message to whatever is returned as a result (if there will be nothing, no message will be sent).
ActorContext.actorSelection(<your-actor-name>) ! someMessage
I think you can watch your actor and if you receive message Terminated you are sure that your actor is not running.
ActorContext.watch(self)

Is spawning a new actor from an existing one thread-safe?

As it was said several times before here, you can spwan a new thread (putting a long-processing computation into actor{} block) inside an actor, and spawned computation will be safely run on the same thread pool (used by the actor scheduler).
actor{
var i = 0
case msg => actor {
// computation
i = i + 1 // is `i` still thread safe?
// looks like it can be access simultaneosly from 2 two threads now
// should I make it #volatile?
}
reply(i)
}
However, will it be thread-safe, and does it follow, in general, the original design, which states that only one thread in a moment of time can work with one actor?
Spawning an actor from another is completely safe.
However, sharing mutable state between actors isn't, regardless of how & where they were spawned.
The whole point of actors is that they should communicate with messages, via their mailboxes. Abuse this model and actors offer no more protection from concurrency issues than you get with raw threads.
In your example, i can indeed be accessed from multiple threads; that doing the computation and the thread calling reply. Perhaps you should reply with aFuture?
reply( future { /* perform computation */ } )
The caller would then be able to react to the futures input channel (non-blocking), or simply apply() (blocking).
Actors can only process one message simultanously, so anything you are doing within your actor is threadsafe by design you have never to think about thread safety.
This is the complete idea behind actors and it's concurrency design.

How to discover that a Scala remote actor is died?

In Scala, an actor can be notified when another (remote) actor terminates by setting the trapExit flag and invoking the link() method with the second actor as parameter. In this case when the remote actor ends its job by calling exit() the first one is notified by receiving an Exit message.
But what happens when the remote actor terminates in a less graceful way (e.g. the VM where it is running crashes)? In other words, how the local actor can discover that the remote one is no longer available? Of course I would prefer (if possible) that the local actor could be notified by a message similar to the Exit one, but it seems not feasible. Am I missing something? Should I continuously polling the state of the remote actor (and in this case I don't know which is the best way to do that) or is there a smarter solution?
But what happens when the remote actor terminates in a less graceful way (e.g. the VM where it is running crashes)
Actor proxy stays alive accepting messages (and loosing them), and waiting for you to restart the JVM with remote actor. Watching for JVM crashes (and other failures happening on the infrastructure level) is far beyond Scala responsibilities. Good choice for that could be monitoring through JMX.
In other words, how the local actor can discover that the remote one is no longer available?
You may define a timeout interval (say 5000 millis). If remote actor doesn't reply during this interval, it's a sign for you that something unexpected is happening to remote actor, and you may either ask it about its state or just treat it as dead.
Should I continuously polling the state of the remote actor (and in this case I don't know which is the best way to do that) or is there a smarter solution?
You may put a kind of a polling load balancer/dispatcher in front of a group of actors, that will use only those actors that are alive and ready to process messages (which makes sense in case of remote actors that may suddenly appear/disappear behind the proxy) -> Can Scala actors process multiple messages simultaneously?
The book Actors in Scala mentions (not tested personally):
Trapping termination notifications.
In some cases, it is useful to receive termination notifications as messages in the mailbox of a monitoring actor.
For example, a monitoring actor may want to rethrow an exception that is not handled by some linked actor.
Or, a monitoring actor may want to react to normal termination, which is not possible by default.
Actors can be configured to receive all termination notifications as normal messages in their mailbox using the Boolean trapExit flag. In the following example actor b links itself to actor a:
val a = actor { ... }
val b = actor {
self.trapExit = true
link(a)
...
}
Note that before actor b invokes link it sets its trapExit member to true;
this means that whenever a linked actor terminates (normally or abnormally) it receives a message of type Exit.
Therefore, actor b is going to be notified whenever actor a terminates (assuming that actor a did not terminate before b’s invocation of link).
So "what happens when the remote actor terminates in a less graceful way"?
It should receive an Exit message even in the case of an abnormal termination.
val b = actor {
self.trapExit = true
link(a)
a ! 'start
react {
case Exit(from, reason) if from == a =>
println("Actor 'a' terminated because of " + reason)
}
}