Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with long initialization of an Akka child actor?

Tags:

scala

akka

actor

I have an actor which creates a child actor to perform some lengthy computations.

The problem is that the initialization of the child actor takes a few seconds and all messages that the parent actor sends to the child between it is created and gets fully initialized are dropped.

This is the logic of the code that I am using:

class ChildActor extends Actor {
  val tagger = IntializeTagger(...) // this takes a few seconds to complete

  def receive = {
    case Tag(text) => sender ! tagger.tag(text)
    case "hello" => println("Hello")
    case _ => println("Unknown message")
  }
}

class ParentActor extends Actor {
  val child = context.ActorOf(Props[ChildActor], name = "childactor")

  // the below two messages seem to get lost
  child ! "hello"
  child ! Tag("This is my sample text")

  def receive = {
     ...
  }
}

How could I get around that problem? Is it possible to make the parent actor wait until the child is fully initialized? I will be using the child actor with routing and possibly on remote actor systems.

EDIT

Following drexin's advice I have change my code into:

class ChildActor extends Actor {
  var tagger: Tagger = _

  override def preStart() = {
    tagger = IntializeTagger(...) // this takes a few seconds to complete
  }

  def receive = {
    case Tag(text) => sender ! tagger.tag(text)
    case "hello" => println("Hello")
    case _ => println("Unknown message")
  }
}

class ParentActor extends Actor {
  var child: ActorRef = _

  override def preStart() = {
    child = context.ActorOf(Props[ChildActor], name = "childactor")

    // When I add
    // Thread.sleep(5000)
    // here messages are processed without problems

    // wihout hardcoding the 5 seconds waiting 
    // the below two messages seem to get lost
    child ! "hello"
    child ! Tag("This is my sample text")
  }

  def receive = {
     ...
  }
}

but the problem remains. What am I missing?

like image 825
twowo Avatar asked Jun 12 '13 09:06

twowo


People also ask

What happens when an actor fails in Akka?

When an actor throws an unexpected exception, a failure, while processing a message or during initialization, the actor will by default be stopped.

How do I terminate Akka actor?

In Akka, you can stop Actors by invoking the stop() method of either ActorContext or ActorSystem class. ActorContext is used to stop child actor and ActorSystem is used to stop top level Actor.

Can an Akka actor stop itself?

An actor can stop itself by returning. Behaviors. stopped as the next behavior. A child actor can be forced to stop after it finishes processing its current message by using the stop method of the ActorContext from the parent actor.

What is ActorSystem in Akka?

Companion object ActorSystem An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors. There are several possibilities for creating actors (see akka.


1 Answers

Don't initialize the tagger in the constructor, but in the preStart hook, this way the messages will be collected in the message box and delivered, when the actor is ready.

edit:

You should do the same for the actor creation in your ParentActor class, because you would have the same problem, if the ChildActor would respond, before the ParentActor is initialized.

edit2:

I created a simple example, but I was not able to reproduce your problems. Following code works perfectly fine:

import akka.actor._

case class Tag(x: String)

class ChildActor extends Actor {
  type Tagger = String => String
  var tagger: Tagger = _

  override def preStart() = {
    tagger = (x: String) => x+"@tagged" // this takes a few seconds to complete
    Thread.sleep(2000) // simulate time taken to initialize Tagger
  }

  def receive = {
    case Tag(text) => sender ! tagger(text)
    case "hello" => println("Hello")
    case _ => println("Unknown message")
  }
}

class ParentActor extends Actor {
  var child: ActorRef = _

  override def preStart() = {
    child = context.actorOf(Props[ChildActor], name = "childactor")

    // When I add
    // Thread.sleep(5000)
    // here messages are processed without problems

    // wihout hardcoding the 5 seconds waiting 
    // the below two messages seem to get lost
    child ! "hello"
    child ! Tag("This is my sample text")
  }

  def receive = {
    case x => println(x)
  }
}

object Main extends App {

  val system = ActorSystem("MySystem")

  system.actorOf(Props[ParentActor])
}

Output is:

[info] Running Main
Hello
This is my sample text@tagged
like image 99
drexin Avatar answered Sep 19 '22 01:09

drexin