I have a question about Akka Timeouts.
For example, I have the Supervisor actor which sends a message to DBActor to start reading the database. The Supervisor sets a timeout of 5 seconds.
The DBActor starts reading the database; it gets the ResultSet, and then enters a loop to iterate the ResultSet rows and build the return value.
Then the Supervisor experiences a Timeout exception and returns a value from the .recover block
My question is ; does the DBActor continue to loop through the ResultSet after the TimeoutException ? Because that would be a resource leak.
The DBActor is independent of the supervisor and will keep processing the records until it is finished or is told to stop. It does not matter that the supervisor has given up on the current request because the DBActor does not know this. If you want the process to stop early, the supervisor will have to send another message to the DBActor to tell it to abort the operation. The supervisor will also have to deal with the case where the results arrive after the timeout has expired.
Also note that Scala cannot "leak" resources as such because it implements garbage collection. If resources are accumulating somewhere it is because a reference to that resource is being held by an object.
Related
I know actors are persistent, They are always alive sitting idle as long as there is nothing to do(no messages in the mailbox), So who monitors the mailbox ?
Is it the Actor itself ? but it doesn't have a thread assigned from dispatcher until its having a message.?
Or, is there any background daemon running monitoring mailboxes of each actors?
As #Sarvesh Kumar Singh mentioned, actor is not by default persistent. You can create persistent actor by extending PersistentActor: Akka Persistence.
In fact, when a actor(cell) is created in the actor system hierarchy, its mailbox(Mailbox is a subclass of Runnable) will be attached to the dispatcher, when the actor is started, the dispatcher will then execute the mailbox runnable(defined in the run method) by polling message from the mailbox queue, if there's a message, it will trigger the defined actor receive method to actually handle the message. Message looping(during this run, the messages in the queue will the be handled into batch, if handling this batch of batch doesn't pass the limit of dispatcher throughput configuration) is also done in the run method by a recursive call of processMailBox defined in mailbox. At the end of each round, the mail box will attach itself to the dispatcher thread pool for execution if there's messages the actor mail box is scheduled for execution the the loop continues. If not, the loop is broken, the next run will be scheduled when there's message sent to the actor, at this moment, message will be dispatched via the dispatcher attached with the actor cell when you call actorRef ! message, this will make the dispatcher to schedule the message handling, check this out: Dispatch::sendMessage and Dispatcher::dispatch. As explained in Dispatchers, dispatcher's throughput can be configured to determine the maximum number of messages to be processed per actor before the thread jumps to the next actor.
I have an actor which receive Int and accumulate result to the buffer. Some times actor can throw exception. What is the best way to restore previous state of buffer into actor after exception ?
BR.
In order to control what happens you need to set the supervisor strategy on the parent actor.
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case e: Exception => {
println(s"got exception ~ ${e.getMessage()}")
Resume // Or Continue, Escalate, Restart, Stop
}
}
If you would like to handle the exception then resume the actor then your handler would return Resume
When resuming, the actor state remains unchanged.
In addition to manub's answer, you should also consider separating
the part that accumulates the value, and
the part that may fail
into two actors as follows:
The accumulating actor should create a child actor. This child actor does the job that can potentially fail, and then sends the result of its job as a message back to its parent. The parent actor receives the result of the job and does the accumulating, or a notification that the child actor has failed. This way, you can, for example, restart failed jobs using various supervision strategies.
For more information on such an approach, see for example this answer Handling Faults in Akka actors
In order to be able to recover the state of a stateful actor you should consider Akka Persistence. You will require a durable store (Cassandra or LevelDB for example) to persist state, and the framework will handle restoring the state for you (provided that you have a PersistentActor).
http://doc.akka.io/docs/akka/current/scala/persistence.html explains in detail how to achieve this.
You can set the Supervisor strategy to Resume. When your Actor throws an exception, the Supervisor will handle the exception and your Actor will throw away the current message and move on to the next one. (Newer versions of Akka let you set a maximum number of retires on the same message)
If instead, you would like your Actor to continue processing the message that caused the exception, you can use a try-catch-finally block.
In my scala application I have an actor A that is the child of the guardian actor. The guardian actor has been given a one for all strategy to escalate on children shutdown.
Under various circumstances, the actor A calls context stop self that usually results in the entire application exiting, which is the desired behavior.
However, I recently observed a scenario where context stop self resulted in an error
Failed to run termination callback, due to [Futures timed out after [5000 milliseconds]]
..and the actor system did not shutdown.
The application does sometimes have hundreds of thousands of actors under Actor A, and I wonder if shutting them down caused some sort of timeout in the termination procedure.
Can anyone help me understand why the behavior described above would happen and should I be using context system shutdown instead to shutdown the system?
I'm currently sending a message to an Akka actor every second for it to perform a task.
If that task (function) is still running when a new message is received by the actor, I would like the actor to do nothing. Basically, I want the actor function to be run only if it's not already running.
What's a good way to do this? Should I use Akka actors or do it another way?
Cheers
Actors process a message at a time. The situation you describe cannot happen.
Akka actors process their messages asynchronously one-by-one, so you can only drop/ignore "expired" messages to avoid extra processing and OutOfMemoryException-s due to actor's Mailbox overflow.
You can ignore expired (more than 1 second old in your case) messages inside your actor:
case class DoWork(createdTime: Long = System.currentTimeMillis)
final val messageTimeout = 1000L // one second
def receive = {
case DoWork(createdTime) =>
if((System.currentTimeMillis - createdTime) < messageTimeout) { doWork() }
}
Or you can create a custom Mailbox which can drop expired messages internally.
Of course, as Robin Green already mentioned, actors in general are not supposed to run long-running operations internally so this approach can be suitable only if your actor doesn't need to process other kind of messages (they will not be processed in time). And in case of high CPU demands you may consider to move your actor on a separate dispatcher.
Is the following statement correct, otherwise how can it be improved?
When an Akka actor is sent a message, a job is submitted to the executor.
When there is a free thread, it calls the job which obtains a lock on
the actor (assuming it can, otherwise another job is taken). The
receive method of the actor is then called and once it completes,
the job is discarded and the thread returned to the pool. The cycle is then repeated.
All the complicated stuff related to concurrent threads is
handled by Akka, freeing the programmer to concentrate on
solving business problems.
More accurate would be:
When a message is sent to an actor, it is placed in this actor's queue called mailbox. At the same time there can be hundreds or thousands of actors having pending messages in their mailboxes. Akka, using limited number of worker threads, selects a subset of such actors and calls their receive method with each and every message from mailbox in chronological order.
More than one thread never handles the same actor. Also Akka may decide to interrupt processing of messages from a mailbox and select different actor to remain fair and avoid starvation. Because one thread is needed for each receive invocation, this method should never block, wait or sleep.