Initializing an actor before he can handle some other messages

I have an actor who creates another one:

class MyActor1 extends Actor {
  val a2 = system actorOf Props(new MyActor(123))
}

The second actor should initialize (bootstrap) itself after its creation, and only after that it should be able to perform another task.

class MyActor2(a: Int) extends Actor {
  //initialized (bootstrapped) itself, potentially a long operation 
  //how?
  val initValue = // get from a server

  //handle incoming messages
  def receive = {
    case "job1" => // do some job but after it initialized (bootstrapped) itself
  }
}

So, the very first thing to do MyActor2is do some initialization work. This may take some time as it requests the server. Only after successful completion should it be able to process incoming messages through receive. Before that - he should not do this.

, (, Future, async, await , AsyncHttpClient). , , .

?

p.s. , .

+4
2

become :

class MyActor2(a: Int) extends Actor {

  server ! GetInitializationData

  def initialize(d: InitializationData) = ???

  //handle incoming messages
  val initialized: Receive = {
    case "job1" => // do some job but after it initialized (bootstrapped) itself
  }

  def receive = {
    case d @ InitializationData =>
      initialize(d)
      context become initialized
  }
}

, . , , Stash:

class MyActor2(a: Int) extends Actor with Stash {

  ...

  def receive = {
    case d @ InitializationData =>
      initialize(d)
      unstashAll()
      context become initialized
    case _ => stash()
  }
}

var , InitializationData :

class MyActor2(a: Int) extends Actor {

  server ! GetInitializationData

  //handle incoming messages
  def initialized(intValue: Int, strValue: String): Receive = {
    case "job1" => // use `intValue` and `strValue` here
  }

  def receive = {
    case InitializationData(intValue, strValue) =>
      context become initialized(intValue, strValue)
  }
}
+9

, - . . . API, prestart.

:

  • , preStart hook, , .
  • , .
  • , context.become, / .
  • , .

( , . ):

class MyActor2(a: Int) extends Actor with Stash{

  def preStart = {
    val future = // do your necessary server request (should return a future)
    future onSuccess {
      context.become(normalReceive)
      unstash()
    }
  }

  def receive = initialReceive

  def initialReceive = {
    case _ => stash()
  }

  def normalReceive = {
    // your normal Receive Logic
  }
}

:

class MyActor2(a: Int) extends Actor with Stash{

  def preStart = {
    val future = // do your necessary server request (should return a future)
    future onSuccess {
      self ! InitializationDone
    }
  }

  def receive = initialReceive

  def initialReceive = {
    case InitializationDone =>
      context.become(normalReceive)
      unstash()
    case _ => stash()
  }

  def normalReceive = {
    // your normal Receive Logic
  }

  case class InitializationDone
}
+4

All Articles