Global variable within akka actor system in Scala

1.8k Views Asked by At

I currently use an akka Actor system in my Scala code. I have a parent actor and a child actor. What i want to do is initiate a List at the parent actor and let the child actor:

i)Generate new elements and send them to parent actor who will attach them to the list. ii)Have access at the list elements at anytime.

How can i achieve the second(ii) part?

3

There are 3 best solutions below

1
On BEST ANSWER

Well, I managed to find a solution.

If you create a variable inside the parent Actor and pass it as a construction parameter to the child Actor , every alteration in this variable is visible if you do not replace it. I will explain with a correct example following a false example.

class ParentActor(/*constructors here*/) extends Actor{
   val list =ListBuffer[Int](1,2)
   child = new ChildActor(list //+other constructors)

   list=ListBuffer[Int](1,2,3) // **wrong** child will see list=List(1,2)
   list+=3         // **right**  child will see list=List(1,2,3) as wanted

}

class ChildActor(list : ListBuffer[Int] /*++ otherconstructors here*/) extends Actor{

       list=ListBuffer[Int](1,2,3,4) // **wrong** parent will see list=List(1,2,3)
       list+=4           // **right**  child will see list=List(1,2,3,4) as wanted

}

3
On

You can choose a specific message to which the Parent can reply disclosing its internal status. See an example below:

  import scala.collection.immutable.Queue

  class Parent extends Actor {
    import Parent._

    // TODO: start children here

    override def receive: Receive = receiveElements(Queue.empty[Element])

    def receiveElements(acc: Queue[Element]): Receive = {
      case e@Element => context.become(receiveElements(acc :+ e))
      case GetElements => sender ! acc
    }
  }

  object Parent {
    case class Element(s: String)
    case object GetElements
  }

Note that the same behaviour is achievable by keeping a var queue internal to the Parent instead of using context.become+recursion.

Also, not designing a way for the queue to be flushed can potentially lead to OOME.

2
On

You must use message passing. Sharing any kind of mutable state between two actors violates every guarantee offered by Akka.

Alternatively, you could share an Agent between your child and parent actors, which would linearize updates to the list while allow synchronous reads.