Async callback from Akka Actor - scala

I have an actor that may receive messages from an external system (UDP/TCP). Based on the content of the incoming data, there are cases when I want the actor to call back to a non-aka part of my code.
In other words, I don't want to call and actor with ask and wait for some incoming data but rather be called back asynchronously.
How can I implement this without e.g. closing over the calling object (the trivial would be pass in a callback on creation of ActorRef but this would capture caller)?

Assuming you have a functional interface handleMessage - that is, a method handleMessage that only accepts immutable data - you can simply wrap it in a Future, run inside the actor's context:
import scala.concurrent.Future
// Inside your actor, this is the implicit execution context holding the thread
// pool the actor executes within. You MUST import this in order for it to be in
// the implicit scope for scala.concurrent.Future.
import context.dispatcher
Future {
handleMessage(messageData)
// If you need to know when this completes, send a message to the initiating
// actor here.
}

Related

this vs self inside akka actor class

Let's say I have a very simple actor class which receives any message and prints to the console.
class SimpleActor extends Actor{
def receive: Receive = {
case message =>
println(s"[${this}][${self}] received message: ${message}")
}
}
val simpleActor = actorSystem.actorOf(Props[SimpleActor], "simpleActor")
simpleActor ! "Hey"
As you can see I am using both this and self here and both has different values. Its output is something like:
[pkg.ActorRunner$SimpleActor#65cca69][Actor[akka://ActorDemo/user/simpleActor#934141660]] received message: Hey
I want to understand the difference between self and this because in complex scenarios(production system) if the actor breaks, for example: throws an exception than I think value for this gets changed.
this is classic java reference to the object extending Actor trait while self is a reference to the ActorRef that is what you need to send messages (! or tell and ? or ask)
You can't send messages to this
You shouldn't pass reference to this outside actor while passing reference to self is perfectly fine, in fact it is sent implicitly when you send a message to an actor from another actor. If you pass this to another object you will be risking actor's state encapsulation. Remember that the only way to communicate with an actor is via messages, i.e. with its ActorRef
self will remain valid after actor restart, aka you can keep sending messages to the same ActorRef (self). Only when the actor is stopped the reference to ActorRef is no longer valid and messages sent to that address will end in Dead Letters.
this will no longer be valid after actor restart. A new object of type Actor is instantiated to clear the actor state that could be compromised due to failure.
What restarting means
Unless the failure is specifically recognizable, the third cause cannot be ruled out, which leads to the conclusion that the internal state needs to be cleared out. If the supervisor decides that its other children or itself is not affected by the corruption—e.g. because of conscious application of the error kernel pattern—it is therefore best to restart the child. This is carried out by creating a new instance of the underlying Actor class and replacing the failed instance with the fresh one inside the child’s ActorRef; the ability to do this is one of the reasons for encapsulating actors within special references. The new actor then resumes processing its mailbox, meaning that the restart is not visible outside of the actor itself with the notable exception that the message during which the failure occurred is not re-processed.
Actor Reference and Path Equality
Note that a restart of an actor caused by a failure still means that it is the same actor incarnation, i.e. a restart is not visible for the consumer of the ActorRef.
What is the Difference Between Actor Reference and Path?
An actor reference designates a single actor and the life-cycle of the reference matches that actor’s life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
You can create an actor, terminate it, and then create a new actor with the same actor path. The newly created actor is a new incarnation of the actor. It is not the same actor. An actor reference to the old incarnation is not valid for the new incarnation. Messages sent to the old actor reference will not be delivered to the new incarnation even though they have the same path.

What is the difference between timers.startSingleTimer and scheduler.scheduleOnce in Akka Actor?

I am designing an actor that should schedule sending a message to itself.
I notice that there are at least two ways to do it.
I would like to understand the difference to choose the right one.
The first is one method of akka.actor.Timers:
def startSingleTimer(key: Any, msg: Any, timeout: FiniteDuration): Unit
The second is the pretty common way with scheduler of actor context system:
final def scheduleOnce(
delay: FiniteDuration,
receiver: ActorRef,
message: Any)(implicit executor: ExecutionContext,
sender: ActorRef = Actor.noSender): Cancellable
Question:
Which is the main difference between them in case of scheduling a
message to itself?
Is it a good idea to pass actor context to scheduleOnce method?
akka.actor.Timers.startSingleTimer
Can be used only within an actor
Allows only scheduling a message to self, ie not possible to schedule a message to some other actors
If actor dies, the active timers are cancelled automatically
Keeps track of active timers by user provided key
context.system.scheduler.scheduleOnce
Can be used to schedule messages outside and inside actors
Requires explicit ActorRef for receiver and optional sender
There is no automatic clean-up process. All should be handled explicitly by calling returned akka.actor.Cancellable
So, if you just need to schedule messages to itself, pick akka.actor.Timers
Is it a good idea to pass actor context to scheduleOnce method?
Not sure in what way you want to do it, but in general actor context must be used only within receive method and not passed outside of an actor neither used in callback methods of Futures.

Akka thread safety with Futures

I have an actor that has a mutable state. In my receive method, I pattern match the messages and call some service that would return a Future. This Future would modify the state in my Actor instance. Is this state not thread safe? Since the Future would be executing in a different thread, is the state in my Actor this guaranteed to be thread safe?
No that will not be threadsafe as you correctly assumed. Futures run on any thread that the execution context provides.
The way to solve this is to pipe it back to the same actor. All actor's inputs must always be messages. You can find the documentation here.
Some example code:
import akka.pattern.pipe
//... inside the Actor somewhere:
val futureResult: Future[YourType] = something.thatReturnsAFuture()
futureResult.pipeTo(self)
And then amend your receive block so the result will be processed after the future completes and it is sent back to this actor:
case result: YourType => //...

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.

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