Akka-Persistence -Is it ok to use mutable states with akka PersistentActor? - scala

Is it ok to use mutable states with akka PersistentActor or shall I use context.become/unbecome with receiveCommand() and not with the receiveRecover() as it will wait for the full recovery before the state is changed.

In general you can't use context.become and friends within a PersistentActor because those affect the receive method, which is provided by the PersistentActor (and handles some internal messages which are implementation details, so you don't really want to duplicate it).
Being more explicit about the mutable state than context.become is a better path.
There is a pattern of wrapping up all the mutable state into a single immutable object (e.g. a Scala case class) and deferring the command handling to that object, which could be as simple as something like:
var state: State = ???
override val receiveCommand: Receive = state.processCommand(_)
You can go further and have your processCommand method on State return, e.g. a (Seq[Event], () => Try[Unit])... this is actually fairly close to what projects like Lagom or Typed Persistence are doing.

Related

Actor accessing things out of scope

I'm using the Akka libraries.
What happens when multiple actors call a function on an object? Would this block other actors from accessing the object?
The reason I ask this is because I want to use JBCrypt with akka actors. And since we can encrypt multiple strings concurrently I have each actor calling JBcrypt.hash(...). Not sure how it works since I think, in scala, objects exist in one place, and I feel like multiple actors using the same object (library) might block the concurrency from actually happening.
Multiple actors calling a function in an object that calls a library will not block unless the library being called uses concurrency control mechanisms such as sychronized, ThreadLocal or an object lock.
For example, calling print on the below Printer object will block:
class BlockingPrinter(){
def print(s: String) = synchronized{s}
}
object Printer{
val printer = new BlockingPrinter()
def print(str: String) = printer.print(str)
}
But calling it on the below Printer object will not
class NonBlockingPrinter(){
def print(s: String) = s
}
object Printer{
val printer = new NonBlockingPrinter()
def print(str: String) = printer.print(str)
}
In summary, the library that you're calling is the one that decides how concurrency is handled. Not the fact that you're calling an object.
It depends on how the function is implemented. If the function accessed some internal mutable state and tries to synchronize in order to achieve thread safety then there is a problem. If it's a pure function and does not access any external state, then it is safe. If the function has the mutable state at least it must contain the mutable state to itself.

Declaring Actor state variables as mutable ones

I am fairly new with Akka framework and Concurrency concepts. And from Akka docs, I understood that only one message in the Actor mailbox would be processed at a time. So single thread would be processing Actor's state at a time. And my doubt is that, so declaring an Actor state/data variable as mutable - 'Var'(Only when 'Val' doesn't fit), will not cause inconsistent Actor states in the case of Concurrency.
I am using Scala for development. In the following Master actor, details of workers is stored in a mutable variable 'workers'. Will it be a problem with concurrency?
class Master extends PersistentActor with ActorLogging {
...
private var workers = Map[String, WorkerState]()
...
}
I think what you are doing is fine. As you said, one of the fundamental guarantees of Akka actors is that a single actor will be handling one message at a time, so there will not be inconsistent Actor states.
Akka actors conceptually each have their own light-weight thread,
which is completely shielded from the rest of the system. This means
that instead of having to synchronize access using locks you can just
write your actor code without worrying about concurrency at all.
http://doc.akka.io/docs/akka/snapshot/general/actors.html
Also, it is a good thing that you're using a var instead of a val with a mutable map :)
Another way to consider coding situations like these is to alter the actor's "state" after each message handled. Eg.:
class Master extends PersistentActor with ActorLogging {
type MyStateType = ... // eg. Map[String, WorkerState], or an immutable case class - of course, feel free to just inline the type...
def receive = handle(initState) // eg. just inline a call to Map.empty
def handle(state: MyStateType): Actor.Receive = LoggingReceive {
case MyMessageType(data) =>
... // processing data - build new state
become(handle(newState))
case ... // any other message types to be handled, etc.
}
... // rest of class implementation
}
While it is true that there is still mutable state happening here (in this case, it is the state of the actor as a whole - it becomes effectively a "non-finite state machine"), it feels better contained/hidden (to me, at least), and the "state" (or "workers") available to the actor for any given message is treated as entirely immutable.

Can it be safe to share a var?

My application has a class ApplicationUsers that has no mutable members. Upon creation of instances, it reads the entire user database (relatively small) into an immutable collection. It has a number of methods to query the data.
I am now faced with the problem of having to create new users (or modify some of their attributes). My current idea is to use an Akka actor that, at a high level, would look like this:
class UserActor extends Actor{
var users = new ApplicationUsers
def receive = {
case GetUsers => sender ! users
case SomeMutableOperation => {
PerformTheChangeOnTheDatabase() // does not alter users (which is immutable)
users = new ApplicationUsers // reads the database from scratch into a new immutable instance
}
}
}
Is this safe? My reasoning is that it should be: whenever users is changed by SomeMutableOperation any other threads making use of previous instances of users already have a handle to an older version, and should not be affected. Also, any GetUsers request will not be acted upon until a new instance is not safely constructed.
Is there anything I am missing? Is my construct safe?
UPDATE: I probably should be using Agents to do this, but the question is still holds: is the above safe?
You are doing it exactly right: have immutable data types and reference them via var within the actor. This way you can freely share the data and mutability is confined to the actor. The only thing to watch out for is if you reference the var from a closure which is executed outside of the actor (e.g. in a Future transformation or a Props instance). In such a case you need to make a stack-local copy:
val currentUsers = users
other ? Process(users) recoverWith { case _ => backup ? Process(currentUsers) }
In the first case you just grab the value—which is fine—but asking the backup happens from a different thread, hence the need for val currentUsers.
Looks fine to me. You don't seem to need Agents here.

Akka tracking when the actors finished

I have following code that traverses through a list of people and calls a callback for each of them in class1.
def syncPeople(callback: Person => _) = Future {
person.findAll(criteria).foldLeft(0L) { (count, obj) =>
callback(obj)
count + 1
}
}
Callback and the call to syncPeople is in class2 and looks similar to this
def getActor(person: Person):ActorRef = {
if(person.isMale) maleActor
else femaleActor
}
def process(person: Person): Unit = {
val workActor = getActor(person)
workActor ! person
} //The actor does the actual work and may be quite intense
def syncPeople(process)
Now, I want to track the total time taken to sync all people. ie when the last workActor completes the work. I am using a third Actor: MonitorActor to keep track of start and end times. The MaleActor, FemaleActor can send messages to this when they process an individual
Whats the best way to keep track of this spawned processes?
I explored
Future.sequence // but the class sending the workActor the message is not an actor. so the future does not receive the message
keeping track of personIds when they finish, but without using a var, to accumulate the received messages in MonitorActor its not possible implement this.. and using var is not preferred way of doing things
What could be other ways of implementing this
Funny, I'm working on a very similar problem to this at the moment. The solution I would suggest is using akka-fsm which keeps track of state.
Essentially in something outside of your state object, do something like generate a Long that represents an id:
def getId(): Long = System.currentTimeMillis() / 1000L
The state object when implemented correctly is immutable, so you just keep reusing this id throughout the transaction.
I know this answer is missing a lot of the implementation details but I'm still working on the implementation myself in my own code. Hopefully after reading about akka-fsm a bit and playing with it, this answer will make sense?
Don't demonize mutable state, it's SHARED mutable state, which causes the most of the problems. You don't have shared mutable state inside an actor, because you always talk to actorRefs and the actors process only one message at a time (no race conditions and other evil stuff). What I'm saying is, it's ok to use a var (unless you spawn some futures inside the actor, which mutate the var, because then your are back to SHARING mutable state). FSM is another solution as #devnulled suggested, but it sounds more like an overkill for your use case.

How to overload bang(!) operator in Scala Actor model?

In an Actor model implementation in Scala, can we override the bang(!) operator.
Can we modify the operation of message passing by overloading this operator?
Example scenario:
I need to include logging of information when any actor invokes another
actor by passing a message. So by overloading the message pass(!) operator, Can I
track the message passing between different actors and avoid including logger
statement for every actor message passing call?
In an Actor model implementation in Scala, can we override the bang(!) operator.
You can, but I would strongly recommend against it.
Example scenario: I need to include logging of information when any actor invokes another actor by passing a message.
This won't work with any actors which don't extend your type: Akka system actors, actors created by libraries, etc.
This can already be done by Akka, just set akka.debug.receive = on.
In Akka you cannot actually override the ! operator, since you cannot create subclasses of ActorRef in a meaningful way (i.e. they would not be generated by the respective factory methods), and the reason for this is that it is not actually what you want (please trust me here).
Your stated use-case is already covered by built-in functionality:
import akka.event.LoggingReceive
def receive = LoggingReceive {
case x => ...
}
which will log a message for each invocation if you enable these configuration settings:
akka {
loglevel = DEBUG
actor.debug {
receive = on // this enables the above
autoreceive = on // same for the likes of PoisonPill, Kill, …
lifecycle = on // will log actor creation, restart, termination
}
}
You can try the following code.
override def !(msg:Any):Unit =
{
//logic for writing to logs..
super.!(msg)
}
This works fine. However, i want to differentiate behavior of !, depending upon the messages I am sending. for example below:
actor_name!(arg1,arg2,arg3)
actor_name1!(arg4, arg5)
How do i differentiate between these two message sending notation in the overriding code?