How to temporary stop Akka actor reading messages from mailbox - akka

I have an actor processing messages and storing its results via asynchronous API (ReactiveMongo). IE when computation is completed actor is asking ReactiveMongo to store computation result and that call is non blocking.
How can I stop actor processing next messages until last ReactiveMongo request feature will be completed? Also mailbox should be able to receive incoming messages.

Blocking solution
Simple and wrong answer: you can do this by blocking the actor, just call Await (or whatever similar method in the language do you use).
It is wrong because Do not block inside the actor.
Not blocking solution
Master\Worker pattern is a good for this problem: http://letitcrash.com/post/29044669086/balancing-workload-across-nodes-with-akka-2
So your worker actor will send the "Work Done" message after ReactiveMongo request feature completion. Then master actor will send new "Do this work" message to the worker.

Related

How to wait for Akka Persistent Actor to persistAll?

I want to send a reply after I have persisted and updated the state of the actor using persistAll. Unfortunately I have not found a callback or onSucces handler to send back a reply after the last event has been persisted.
This is a shortcoming of the API, there is no built in way to react on all persistAll completing, you will have to keep a counter or a set of completed persists yourself and only trigger your logic when the last persist completes.
As far as I remember this cannot be easily fixed because it would break binary and source compatibility.
In the "next generation" persistent actors (in Akka typed) this works more as you would expect and the side effect you want to execute on successful persist of the events will only execute once, when all the events are complete.

Use case for Akka PoisonPill

According to the Akka docs for PoisonPill:
You can also send an actor the akka.actor.PoisonPill message, which will stop the actor when the message is processed. PoisonPill is enqueued as ordinary messages and will be handled after messages that were already queued in the mailbox.
Although the usefulness/utility of such a feature may be obvious to an Akka Guru, to a newcomer, this sounds completely useless/reckless/dangerous.
So I ask: What's the point of this message and when would one ever use it, for any reason?!?
We use a pattern called disposable actors:
A new temporary actor is created for each application request.
This actor may create some other actors to do some work related to the request.
Processed result is sent back to client.
All temporary actors related to this request are killed. That's the place where PoisonPill is used.
Creating an actor implies a very low overhead (about 300 bytes of RAM), so it's quite a good practise.

AKKA actor Stop and the pending messages in the mail box

Based on my usecase, once the required message comes in, the actor should be stopped. There may be pending messages in the mail box which should be deleted. Wondering if calling stop on the actor is enough?
Thanks,
cabear
From the documentation:
Stopping Actors
Actors are stopped by invoking the stop method of a ActorRefFactory, i.e. ActorContext or ActorSystem. Typically the context is used for stopping child actors and the system for stopping top level actors. The actual termination of the actor is performed asynchronously, i.e. stop may return before the actor is stopped.
Processing of the current message, if any, will continue before the actor is stopped, but additional messages in the mailbox will not be processed. By default these messages are sent to the deadLetters of the ActorSystem, but that depends on the mailbox implementation.
So calling stop on the actor is enough: pending messages in the mailbox will not be processed.

Using spray client (sendReceive) within an actor

The use case is this:
An Actor is bind to spray IO - receiving and handling all inbound HTTP requests coming through a specified port.
For each inbound request the actor needs to send an outbound asynchronous http request to a different external endpoint, get back an inbound response and send a response back to originating party.
Using spray's client sendReceive returns a future. This means the actor will continue to handle the next inbound message on it's mailbox without waiting for a response of the outbound request it just sent, in the same time the response for the outbound request might arrive and execute on the Future callback, since it is not queued on the actor's mailbox it might be executed in parallel breaking the idea of an actor being executed by only one thread in a given time.
I wonder how this use case can be handled without breaking the actor thread encapsulation, how can an actor make use of spray-client (for sending/receiving asynchronous http events) in an actor safe way?
It is perfectly safe to complete with the future, not the actual value in spray-routing, so for instance, you can do the following:
get {
comlete {
val resultFuture: Future[Result] = ...
val resultFuture.onComplete {....}
resultFuture
}
}
Of course, you will need to make sure that you handle timeouts and error conditions as well.
The question is which thread executes the callback, if it is not queued on the actor's mailbox it could be a parallel execution to the actor receive handling, which might break its thread encapsulation...
To my understanding, there is the same issue with akka actor 'ask' method which returns a Future, they provide a warning not to execute operations on the actor's mutable state from within the callback since it may cause synchronization problems. see: http://doc.akka.io/docs/akka/snapshot/scala/actors.html
"Warning:
When using future callbacks, such as onComplete, onSuccess, and onFailure, inside actors you need to carefully avoid closing over the containing actor’s reference, i.e. do not call methods or access mutable state on the enclosing actor from within the callback. This would break the actor encapsulation and may introduce synchronization bugs and race conditions because the callback will be scheduled concurrently to the enclosing actor. Unfortunately there is not yet a way to detect these illegal accesses at compile time."

Actor model with Akka.NET: how to prevent sending messages to dead actors

I am using Akka.NET to implement an actor system in which some actors are created on demand and are deleted after a configurable idle period (I use Akka's "ReceiveTimeout" mechanism for this). Each of these actors is identified by a key, and there should not exist two actors with the same key.
These actors are currently created and deleted by a common supervisor. The supervisor can be asked to return a reference to the actor matching a given key, either by returning an existing one or creating a new one, if an actor with this key doesn't exist yet. When an actor receives the "ReceiveTimeout" message, it notifies the supervisor who in turn kills it with a "PoisonPill".
I have an issue when sending a message to one of these actors right after it has been deleted. I noticed that sending a message to a dead actor doesn't generate an exception. Worse, when sending an "Ask" message, the sender remains blocked, waiting indefinitely (or until a timeout) for a response that he will never receive.
I first thought about Akka's "Deatchwatch" mechanism to monitor an actor's lifecycle. But, if I'm not mistaken, the "Terminated" message sent by the dying actor will be received by the monitoring actor asynchronously just like any other message, so the problem may still occur in between the target actor's death and the reception of its "Terminated" message.
To solve this problem, I made it so that anyone asking the supervisor for a reference to such an actor has to send a "close session" message to the supervisor to release the actor when he doesn't need it anymore (this is done transparently by a disposable "ActorSession" object). As long as there are any open sessions on an actor, the supervisor will not delete it.
I suppose that this situation is quite common and am therefore wondering if there isn't a simpler pattern to follow to address this kind of problem. Any suggestion would be appreciated.
I have an issue when sending a message to one of these actors right after it has been deleted. I noticed that sending a message to a dead actor doesn't generate an exception.
This is by design. You will never receive an exception upon attempting to send a message - it will simply be routed to Deadletters and logged. There's a lot of reasons for this that I won't get into here, but the bottom line is that this is intended behavior.
DeathWatch is the right tool for this job, but as you point out - you might receive a Terminated message after you already sent a message to that actor.
A simpler pattern than tracking open / closed sessions is to simply use acknowledgement / reply messages from the recipient using Ask + Wait + a hard timeout. The downside of course is that if your recipient actor has a lot of long-running operations then you might block for a long period of time inside the sender.
The other option you can go with is to redesign your recipient actor to act as a state machine and have a soft-terminated or terminating state that it uses to drain connections / references with potential senders. That way the original actor can still reply and accept messages, but let callers know that it's no longer available to do work.
I solved this problem with entity actors created through Akka's Cluster Sharding mechanism:
If the state of the entities are persistent you may stop entities that are not used to reduce memory consumption. This is done by the application specific implementation of the entity actors for example by defining receive timeout (context.setReceiveTimeout). If a message is already enqueued to the entity when it stops itself the enqueued message in the mailbox will be dropped. To support graceful passivation without losing such messages the entity actor can send ShardRegion.Passivate to its parent Shard. The specified wrapped message in Passivate will be sent back to the entity, which is then supposed to stop itself. Incoming messages will be buffered by the Shard between reception of Passivate and termination of the entity. Such buffered messages are thereafter delivered to a new incarnation of the entity.