What are the dangers of using an object as an AKKA actor? - scala

In the code below I'm using an AKKA actor MonitorActor even though it's an object. I never see this pattern in production code although it seems to work well.
Does the below code have concurrency issues as a result of using an object as as Actor?
Are there any AKKA actor related 'gotchas' on show here?
case class SomeEvent(member: String)
class Example(eventBus: EventBus)(implicit actorSystem: ActorSystem) {
val members: AtomicReference[Set[String]] = new AtomicReference(Set())
actorSystem.actorOf(Props(MonitorActor))
private object MonitorActor extends Actor {
eventBus.subscribe(classOf[SomeEvent])
var isEnough = false
override def receive: Receive = {
case SomeEvent(member: String) =>
val newMembers = members.updateAndGet(_ + member)
if (newMembers.size >= 10) {
isEnough = true
}
}
}
}

One immediate question arising from this "pattern" is: what happens if the Actor is added to the actorSystem twice:
actorSystem.actorOf(Props(MonitorActor))
actorSystem.actorOf(Props(MonitorActor))
This is not a trivial question. In large code bases there can be multiple files/packages where an Actor is materialized so the above scenario will likely come up if only by accident.
At best, each SomeEvent is processed twice by the exact same logic. At worst you will get into nasty race conditions with isEnough. So lets assume the best case.
Even in the best case scenario each SomeEvent will be processed by the exact same logic. This isn't bad in the question's example because members is a Set. But if it were a List you would start to get double insertions of the same event.
Another issue is having to protect ourselves from race conditions involving members. A good reason for members to be an AtomicReference is to resolve the situation where the two "independent" Actors are trying to access members at the same time. But this goes against the entire purpose of the Actor model. From the original 1973 formalism (emphasis mine):
The architecture is general with respect to control structure and does
not have or need goto, interrupt, or semaphore primitives.
A similar description can be found in the akka documentation's introduction (emphasis mine):
The Actor Model provides a higher level of abstraction for writing
concurrent and distributed systems. It alleviates the developer from
having to deal with explicit locking and thread management, making it
easier to write correct concurrent and parallel systems.
So we have effectively broken the Actor model framework and all we got was not having to call a constructor. Contrast the question's example code with the "preferable" implementation:
class MonitorActor() extends Actor {
val members: Set[String] = Set.empty[String]
eventBus.subscribe(classOf[SomeEvent])
var isEnough = false
override def receive: Receive = {
case SomeEvent(member: String) => {
members add member
isEnough = members.size >= 10
}
}
}
Now the developer doesn't have to worry about semaphores, race conditions, thread contention, ... All of the logic and functionality within an Actor can be understood from a serial perspective.

Related

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.

Rewrite the Scala actors in Akka

Update: I've rewritten it in wonky-style and posted it on github - I would appreciate some feedback: https://github.com/drozzy/parallel-discrete-event-akka/tree/master/src/main/scala
Can anyone help me re-write "Parallel discrete event simulation" example from the "Chapter 32: Actors and Concurrency" from Programming in Scala, 2nd, by Martin Odersky?
It was written originally in Scala actors, but translating to Akka I encouter a lot of problems.
Some examples
Actor inheritance (p. 708)
Code like this:
trait Simulant extends Actor
class Wire extends Simulant
I have no idea how to translate to Akka, since in my understanding we never directly instantiate them.
Main Loop
The author constantly uses loops in actors, and I have no idea what they are about:
def act() {
loop {
if (running && busySimulants.isEmpty)
advance()
reactToOneMessage()
}
}
Types
Mostly though, I am struggling with strong types -- it seems Akka, due to requiring ActorRefs prevents me from depending on a specific type of an actor. For example, in the book, the following:
trait Simulant extends Actor {
val clock: Clock
...
depends on a strongly-typed actor Clock. And then it is simply "instantiated" in the implementing actor:
class Wire(name: String, init: Boolean) extends Simulant {
def this(name: String) { this(name, false) }
def this() { this("unnamed") }
val clock = Circuit.this.clock
In my implementation I have something along the lines of:
trait Simulant extends Actor {
val clock: ActorRef
...
and I have no idea how to "instantiate" it. What I have now (untested) is:
class Wire(val clock:ActorRef, name:String, init: Boolean) extends Actor{
def this(clock:ActorRef, name:String) {this(clock, name, false)}
def this(clock:ActorRef){this(clock, "unnamed")}
so I just end up draggin the actor refs around the constructors!
Hooking up components
How do I hook up components to each other? For example, hook-up an AndGate to a Wire - such that any time a signal on the wire changes it sends a message to the gate.
I do it by sending Add messages (i.e. AndGate sends Add to Wire so that wire can add it to the list of its subscribers), and so have to wait for all of them to arrive before starting the simulation. Is there any way to avoid that (the waiting)? (In original implementation the with Scala Actors, some actors were just accessed from global scope, and sometimes actors called other actor's methods directly!)
Source Code
The source code of the example can be found in full at the following url:
http://booksites.artima.com/programming_in_scala_2ed/examples/html/ch32.html
under the heading: 32.6 A longer example: Parallel discrete event simulation
P.S.: I'm new to akka, so forgive my ignorance.
I can not provide any migrated source code, but this link might help you:
actors migration guide.
Some comments:
Actor Inheritance
You can do this in Akka, but class Wire has to implement the receive method.
Main Loop
In Akka you implement the receive method instead of the main loop.
Types
You can use an ActorRef as constructor parameter, but it has to be created (and started) before calling the constructor, e.g. with context.system.actorOf(...).
And there is something called Typed Actors in Akka.
I also strongly encourage you to have a look at the documentation.
EDIT
I had a (quick) look at the source code, these are my findings:
In Scala it is not so common as in Java (and not enforced) that only one public class exists per file (although it can improve compile speed).
Demo.scala: Line 11, Use var instead of val
Constructor initialization (e.g. in FullAdder, Gate, ...): You should be careful about
that, because the constructor is executed every time the actor is restarted; maybe using
the preStart method would be better.
FullAdder, HalfAdder: An actor who doesn't react to messages (or only returning Unit) is a
strange thing in my opinion. Maybe you find another solution for constructing an adder.
Clock.advance: Using return is not good scala style (and I believe it doesn't work
in this case). Use else instead.

Alternatives to using "var" for state with actors?

I have found myself using vars fairly often with akka actors to maintain state. For example, if I my actor needs to maintain a list of items, I might do something like:
class ListActor extends Actor{
var xs : List[Int] = List()
def receive = {
case x : Int => xs = x :: xs
}
}
Using the mutable variable seems to go against the spirit of Scala. Alternatively I have used this:
class ListActor2 extends Actor{
import context._
def collect_ints(accu : List[Int]) : Receive = {
case x : Int => become(collect_ints(x :: accu))
}
def receive = collect_ints(Nil)
}
I like how this looks more, but do I have to worry about the stack overflowing?
I am aware of the FSM trait and have used that before also, but for some situations it seems like too much.
What is the recommended way of maintaining simple state? Are there other alternatives that I am unaware of?
Also, is it generally a bad sign if I find myself needing mutable variables often? Am I not using the actor model properly?
I don´t see any problem with var for simple state in the actor model.
By design Akka prevents the actor´s state of getting corrupted or locked by concurrent access to the state variables.
As long as you are not exposing your state to other threads with the use of Future for instance, the use of var for simple state should not be a problem.
There are two variants of the become method: one that pushes behavior onto a stack, and one that doesn't. The latter is the default, so you don't have to worry about the behavior stack becoming too large. Using become to manage state in this manner is a perfectly valid use for it.
The Akka FSM is actually a very compact idiom for maintaining state in an actor system as in this example:
sealed trait State
case object Active extends State
class ListActor extends Actor with FSM[State,List[Int]] {
startWith(Active,List[Int]())
when(Active) {
case Event(x:Int,xs) => stay using x :: xs
}
}
Having used all the alternatives discussed here, FSM takes my vote for anything that is a shade more complex than trivial.

Akka actors + Play! 2.0 Scala Edition best practices for spawning and bundling actor instances

My app gets a new instance of Something via an API call on a stateless controller. After I do my mission critical stuff (like saving it to my Postgres database and committing the transaction) I would now like to do a bunch of fire-and-forget operations.
In my controller I send the model instance to the post-processor:
import _root_.com.eaio.uuid.UUID
import akka.actor.Props
// ... skip a bunch of code
play.api.libs.concurrent.Akka.system.actorOf(
Props[MySomethingPostprocessorActor],
name = "somethingActor"+new UUID().toString()
) ! something
The MySomethingPostprocessorActor actor looks like this:
class MySomethingPostprocessorActor extends Actor with ActorLogging {
def receive = {
case Something(thing, alpha, beta) => try {
play.api.libs.concurrent.Akka.system.actorOf(
Props[MongoActor],
name = "mongoActor"+new UUID().toString()
) ! Something(thing, alpha, beta)
play.api.libs.concurrent.Akka.system.actorOf(
Props[PubsubActor],
name = "pubsubActor"+new UUID().toString()
) ! Something(thing, alpha, beta)
// ... and so forth
} catch {
case e => {
log.error("MySomethingPostprocessorActor error=[{}]", e)
}
}
}
}
So, here's what I'm not sure about:
I know Actor factories are discouraged as per the warning on this page. My remedy for this is to name each actor instance with a unique string provided by UUID, to get around the your-actor-is-not-unique errors:
play.core.ActionInvoker$$anonfun$receive$1$$anon$1:
Execution exception [[InvalidActorNameException:
actor name somethingActor is not unique!]]
Is there a better way to do the above, i.e. instead of giving everything a unique name? All examples in the Akka docs I encountered give actors a static name, which is a bit misleading.
(any other comments are welcome too, e.g. the if the bundling pattern I use is frowned upon, etc)
As far as I'm aware the name paramater is optional.
This may or may not be the case with Akka + Play (haven't checked). When working with standalone actor systems though, you usually only name an actor when you need that reference for later.
From the sounds of it you're tossing out these instances after using them, so you could probably skip the naming step.
Better yet, you could probably save the overhead of creating each actor instance by just wrapping your operations in Futures and using callbacks if need be: http://doc.akka.io/docs/akka/2.0.3/scala/futures.html

garbage collecting scala actors

Scenario: I have this code:
class MyActor extends Actor {
def act() {
react {
case Message() => println("hi")
}
}
}
def meth() {
val a = new MyActor
a.start
a ! Message()
}
is the MyActor instance garbage collected? if not, how do i make sure it is? if I create an ad-hoc actor (with the 'actor' method), is that actor GCed?
This thread on the scala-user mailing list is relevant.
There Phillip Haller mentions using a particular scheduler (available in Scala 2.8) to enable termination of an Actor before garbage collection, either on a global or per-actor basis.
Memory leaks with the standard Actor library has lead to other Actor implementations. This was the reason for David Pollak and Jonas Boner's Actor library for Lift that you can read much more about here: http://blog.lostlake.org/index.php?/archives/96-Migrating-from-Scala-Actors-to-Lift-Actors.html
Have you tried adding a finalize method to see whether it is? I think the answer here is that the actors subsystem behaves no different to how you would expect it to: it does not cache any reference to your actor except in a thread-local for the duration of processing.
I would therefore expect that your actor is a candidate for collection (assuming the subsystem correctly clears out the ThreadLocal reference after the actor has processed the message which it does indeed appear to do in the Reaction.run method).