How to prevent message reordering using PriorityExecutorBasedEventDrivenDispatcher? - scala

My Akka FSM actor has the need to prioritize messages dependent on type. To be specific, the actor receives messages in one of these categories, in prioritized order:
Messages that triggers state transitions
Messages that query the current state
Messages that causes the actor to perform some work ("WorkMsg")
According to the Akka docs, messages can be prioritized according to the list above with a PriorityExecutorBasedEventDrivenDispatcher containing a PriorityGenerator. I've implemented the FSM actor with this dispatcher and it works well.
The problem is that this dispatcher also reorders WorkMsgs, which is not what I want.
WorkMsgs contain a timestamp and are sent to the FSM actor sorted by this timestamp. When the FSM actor processes WorkMsgs, it discards WorkMsgs that are older than the previous WorkMsg. So if these are reordered, I lose data.
Without the PriorityExecutorBasedEventDrivenDispatcher, WorkMsgs are not reordered, but then the priorities in the list above are not satisfied.
How can I maintain the priorities in the list above, while preventing reordering of messages of the same priority?

A prioritizing proxy actor can prioritize messages to be sent to your worker actor. You will have to sort and store the incoming messages as well as implement the prioritization logic. The worker will additionally have to respond to the proxy after each message to let it know that it is ready for more work.

Related

Akka Actors - Change default behavior of messages arriving in actors

Is it possible in Akka Actors to install some kind of 'hook' that allows you to run a self-defined piece of code every time a new message arrives in an actor? Note, this is not the moment when the actor starts handling the message with receive but the moment when the message arrives in the actor and is put into its mailbox. Also note that I want to change the default behavior, not just the behavior for one individual actor. Ideally I would change this behavior at just one spot throughout my code and it would affect all actors automatically, or by only requiring 1-2 lines of code in each file/actor (such as an import statement).
For example, using this hook it should be possible to log a message every time it arrives or to calculate and print the fibonacci of the size of the mailbox before/after insertion.
If you control the spawning of the actor (or are willing to use this mailbox as the default for actors which don't specifically set a mailbox), you can use a custom mailbox. See the docs for details.

Handling dead actors in Akka Typed

I have some actors that kill themselves when idle or other system constraints require them to. The actors that have ActorRefs to them are watching for their Terminated(ref), but there is a race condition of messages meant for the actors being sent before the termination arrives and I'm trying to figure out a clean way to handle that.
I was considering subscribing to DeadLetter and using that to signal the sender that their ref is stale and that they need to get or spawn a new target ActorRef.
However, in Akka Typed, I cannot find any way to get to dead letters other than using the untyped co-existence path, so I figure I'm likely approaching this wrong.
Is there a better pattern for dealing dead downstream refs and re-directing messages to a new downstream refs, short of requiring some kind of ack hand-shake for every message?
Consider dead letters as a debugging tool rather something to use to implement delivery guarantees with (true for both Akka typed and untyped).
If an actor needs to be certain that a message was delivered the message protocol will need to include an an ack. To do resending the actor will also need to keep a buffer for in-flight/not yet acknowledged messages to be able to resend.
We have some ideas on an abstraction for different levels of reliability for message delivery, we'll see if that fits in Akka 2.6 or happens later though, prototyped in: https://github.com/akka/akka/pull/25099

Where to put calculation executed regularly that updates actor's internal state?

I am learning Scala and Akka.
In the problem I am trying to solve I want an actor to be reading a real-time data stream and perform a certain calculation that would update its state.
Every 3 seconds I am sending a request through a Scheduler for the actor to return to its state.
While I have pretty much everything implemented, with my actor having a broadcaster and receiver and the function to update the state right. I am not entirely sure how to do it, I could potentially put the calculations always running in a separate thread inside the actor but I would like to now if there is a more elegant way to make this in scala.
I would suggest to divide the work between two actors. The parent actor would manage child worker actor and would track the state. It sends a message to the child worker actor to trigger data processing.
The child worker actor processes the data stream - don't forget to wrap the processing into a Future so that it doesn't block the actor from processing messages. It also periodically sends messages to the master with current state. So the child worker is stateless, it sends notifications when its state changes.
If you want to know the current state of the work overall, you ask the master. In principle, you can merge this into one actor which sends the status message to itself. I wouldn't update the state directly to avoid concurrency issues. The reason is that the data processing work running in the Future can possible run on a different thread than message processing.

Akka: what is the reason of processing messages one at a time in an Actor?

It is said:
Akka ensures that each instance of an actor runs in its own lightweight thread and that messages are processed one at a time.
Can you please explain what is the reason of processing messages one at a time in an Actor?
This way we can guarantee thread safety inside an Actor.
Because an actor will only ever handle one message at any given time, we can guarantee that accessing the actor's local state is safe to access, even though the Actor itself may be switching Threads which it is executing on. Akka guarantees that the state written while handling message M1 are visible to the Actor once it handles M2, even though it may now be running on a different thread (normally guaranteeing this kind of safety comes at a huge cost, Akka handles this for you).
It also originates from the original Actor model description, which is an concurrency abstraction, described as actors who can only one by one handle messages and respond to these by performing one of these actions: send other messages, change it's behaviour or create new actors.

Akka FSM actor and round-robin routing

I want to convert some set of actors into FSM using Akka FSM. Currently system is designed in the way that every actor knows what to do with results of it's action and which actor is next in sequence of processing.
Now I want to have some sort of dedicated actors, which are doing only things they should know (and now know about entire message routing), and central FSM, which knows how to route messages and process transformation flow.
Client sends some request to FSM actor, FSM actor - on transition to next state - sends message to some actor in onTransition block. That actor replies to sender with some message, which is processed inside FSM state somehow until request is finished.
So far everything looks good, however I'm not sure what will happen if multiple clients will start interaction with FSM actor. Will the "workflow" be recorded somewhere, so flows from different clients won't collide at some point (like, FSM actor receives message from another client instead of originating one)?
Is it safe to have say 10 FSM actors and round-robin router, or I need to create new FSM actor on every request from client, and then kill it once finished?
Each Akka FSM actor will have only one state at a time, so you can't use multiple FSM actors with a round-robin router in this scenario. You may consider to create a new FSM actor on every request from a client. There are other options (a shared multi-user non-Akka FSM and a pool of FSM actors which may be "busy") but creation of a per-user FSM should be better solution because of the light-weight nature of Akka actors.