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.
Related
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.
I am writing a library that provides a distributed algorithm. The idea being that existing applications can add the library to use the algorithm. The algorithm is in a library module and it abstracts the actual transmission of data over the network behind a trait. An application that uses the algorithm has to provide the actual network transport code. In code it looks something like the following:
// library is really a separate project not a single object
object Library {
// handle to a remote server
trait RemoteProcess
// concrete server need to know how to actually send to a real remote process
trait Server {
def send(client: RemoteProcess, msg: String)
}
}
// the application uses the library and provides the concrete transport
object AkkaDemoApplication {
// concreate ref is a m wrapper to an actor ref in demo app
case class ConcreteRemoteProcess(ref: akka.actor.ActorRef) extends Library.RemoteProcess
class AkkaServer extends Library.Server {
// **WARNING** this wont compile its here to make my question
override def send(client: ConcreteRemoteProcess, msg: String): Unit = client.ref ! msg
}
}
A couple of options I have considered:
Have the signature of the AkkaServer method overload the library trait method then perform an unsafe cast to ConcreteRemoteProcess. Yuk!
Have the signature of the AkkaServer method overload the library trait method then pattern match on the RemoteProcesss argument give a ConcreteRemoteProcess. This is no better than an unsafe cast in terms of blowing up at runtime if the wrong thing is passed.
Make the library server generic in terms of the RemoteProcess.
An example of option 3 looks like:
object Library {
trait Server[RemoteProcess] {
def send(client: RemoteProcess, msg: String)
}
}
object Application {
class AkkaServer extends Library.Server[ActorRef] {
override def send(client: ActorRef, msg: String): Unit = client ! msg
}
}
I tried option 3 and it worked but the generic type ended up be stamped on just about every type throughout the entire library module. There was then a lot of covariant and contravariant hassles to get the algorithmic code to compile. Simply to get compile time certainty at the one integration point the cognitive overhead was very large. Visually the library code is dominated by the generic signatures as though understanding that is critical to understanding the library when in fact it's a total distraction to understanding the library logic.
So using the genetic works and gave me compile time certainly but now I wished I had gone with the option 2 (the pattern match) with the excuse "it would fail fast at startup if someone got it wrong lets keep it simple".
Am I missing some Scala feature or idiom here to get compile time certainty without the cognitive overhead of a "high touch" generic that all the library code touches but ignores?
Edit I have considered that perhaps my code library is badly factored such that a refactor could move the generic to the boundaries. Yet the library has already been refactored for testability and that breakup into testable responsibilities is part of the problem of the generic getting smeared around the codebase. Hence my question is: in general is there another technique I don't know about to avoid a generic to provide a concrete implementation to an abstract API?
I think you are coupling your algorithm and Akka too closely. Further more, I assume the server to send data to the remote client that performs some operation and sends back the result
Answer
Why not
object Library {
// handle to a remote server
trait RemoteProcessInput
trait RemoteProcessResult
// concrete server need to know how to actually send to a real remote process and how to deal with the result
trait Server {
def handle(clientData: RemoteProcessInput) : Future[RemoteProcessResult]
}
}
A concrete implementation provides the implementation with Akka
object Application {
class AkkaServerImpl(system: ActorSystem)
extends Library.Server {
override def handle(clientData: RemoteProcessInput)
: ActorRef, msg: String): Future[RemoteProcessResult] = {
// send data to client and expect result
// you can distinguish target and msg from the concrete input
val ref : ActorRef = ??? // (resolve client actor)
val msg = ??? // (create your message based on concrete impl)
val result = ref ? msg // using ask pattern here
// alternatively have an actor living on server side that sends msgs and receives the clients results, triggered by handle method
result
}
}
}
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.
In scala cookbook: 13.3. How to Communicate Between Actors I see this
class Ping(pong: ActorRef) extends Actor { // OMG - ActorRef - no type, help!
var count = 0
def incrementAndPrint { count += 1; println("ping") }
def receive = {
case StartMessage =>
incrementAndPrint
I have got also a few places in my own code where I have this ActorRef I don't like it as I liked type safety. Is there a way to avoid that in the above pong example?
Side Note: I understand I can use "actorFor" with naming, but as a DI freak I rather pass it in constructor / parameter.
Some stuff is in the works for Akka 3.0 eg see this teaser thread: https://mobile.twitter.com/RayRoestenburg/status/510511346040197120
There is a pattern for type safety now using a custom ask (the question mark). Here is a blog about it:
http://www.warski.org/blog/2013/05/typed-ask-for-akka/
This is a little clunky though and may not be worth the trouble.
Another approach is to create typed APIs and wrap your actors in them.
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