postRestart 和 preRestart 方法没有在 akka actots 中被调用

postRestart and preRestart methods are not getting invoke in akka actots

我正在关注 this tutorial 这是我的代码

case class ArtGroupDeleteFromES (uuidList:List[String]) 
class ArtGroupDeleteESActor extends Actor{
val log = LoggerFactory.getLogger(this.getClass)
    override def preStart() {
      log.debug("preStart  Starting ArtGroupDeleteESActor instance hashcode # {}",
       this.hashCode())
      }

    override def postStop() {
      log.debug("postStop Stopping ArtGroupDeleteESActor instance hashcode # {}",
       this.hashCode())
      }

    override def preRestart(reason: Throwable, message: Option[Any]) {
      log.debug("I am restarting")
      log.debug("ArtGroupDeleteESActor: preRestart")
      log.debug(s" MESSAGE: ${message.getOrElse("")}")
      log.debug(s" REASON: ${reason.getMessage}")
      super.preRestart(reason, message)
      }

    override def postRestart(reason: Throwable) {
      log.debug("restart completed!")
      log.debug("ArtGroupDeleteESActor: postRestart")
      log.debug(s" REASON: ${reason.getMessage}")
      super.postRestart(reason)
      }
def receive = {
  case ArtGroupDeleteFromES(uuidList) =>
 throw new Exception("Booom")
  sender ! true
   }
  case  message => 
    log.warn("Received unknown message: {}", message)
    unhandled(message)
 }

}

这是我向这位演员发送消息的方式

class ArtGroupDeletionActor extends Actor{

  val log = LoggerFactory.getLogger(this.getClass)
 override val supervisorStrategy = OneForOneStrategy(
                                    maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
    case _:Exception => Restart
  }
 val artGroupDeleteESActor=context.actorOf(Props[ArtGroupDeleteESActor]
      .withDispatcher("akka.actor.ArtGroupDeleteESActor-dispatcher")
      ,name = "ArtGroupDeleteESActor")

   def receive = {

    case DeleteArtGroup(uuidList) =>
      val future1  = ask(artGroupDeleteESActor, ArtGroupDeleteFromES(uuidList)).mapTo[Boolean]
      var isDeletedfromES = Await.result(future1, timeout.duration)
    case message =>
      log.warn("Unhandled message received : {}", message)
      unhandled(message)
  }
}

object test extends App{
 val artGroupDeletionActor=system.actorOf(Props[ArtGroupDeletionActor]
      .withDispatcher("akka.actor.ArtGroupDeletionActor-dispatcher")
      ,name = "ArtGroupDeletionActor")
     artGroupDeletionActor ! DeleteArtGroup(List("123"))
}

未调用 PostRestart() 和 preRestart() 方法,但调用了 preStart() 和 postStop(),请指导我哪里做错了

(为简单起见,从现在起我将称你的演员为 ParentChild

这里发生的事情是,当Child.receive内部发生异常时,它不会向Parent发送响应,而是actor系统发送一些用于监督策略的控制指令。但是,ParentAwait 上被阻塞,等待 future1 完成,这只发生在 timeout 超过之后,然后,反过来,一个 TimeoutException 是扔进 Parent.receive,杀死(重启)Parent actor 本身,因此 Child 中异常的监督消息然后传递给 deadLetters,永远不会重启 Child.

你不应该,永远,永远 阻塞在 actor 内部,所以这是不正确的:

  val future1 = ask(artGroupDeleteESActor, ArtGroupDeleteFromES(uuidList)).mapTo[Boolean]
  var isDeletedfromES = Await.result(future1, timeout.duration)

相反,您必须在并发环境中使用某种消息标识来区分一个回复与另一个回复,或者向 Future 添加 onComplete 并在 self 中发送一条消息闭包(注意:除了向 Future 发送消息外,不应在闭包内执行任何逻辑!)。

所以,选项 A:

case class ArtGroupDeleteFromES(id: Long, uuidList: List[String])
case class ArtGroupDeleteFromESResult(id: Long, success: Boolean)

class Parent extends Actor {
  override val supervisionStrategy = ...
  var msgId = 0L
  var pendingRequesters = Map.empty[Long, ActorRef]
  val child = context.actorOf(Props[Child])

  def nextId = {
    msgId += 1
    msgId
  }

  def receive = {
    case DeleteArtGroup(uuidList) =>
      val id = nextId
      pendingRequesters += id -> sender() // store a reference to the sender so that you can send it a message when everything completes
      child ! DeleteArtGroupFromES(nextId, uuidList)
    case ArtGroupDeleteFromESResult(id, success) =>
      // process result...
      pendingRequesters(id) ! "done"
      pendingRequesters -= id
  }
}

选项B:

case class ArtGroupDeleteFromES(uuidList: List[String])
case class ArtGroupDeleteFromESResult(replyTo: ActorRef, success: Boolean)

class Parent extends Actor {
  override val supervisionStrategy = ...
  val child = context.actorOf(Props[Child])

  def receive = {
    case DeleteArtGroup(uuidList) =>
      val requester = sender() // when the future completes, sender may have already changed, so you need to remember it
      (child ? DeleteArtGroupFromES(uuidList)).onComplete {
        case Success(success) => self ! ArtGroupDeleteFromESResult(requester, success)
        case Failure(e) =>
          log.warn("Could not delete...", e) 
          self ! ArtGroupDeleteFromESResult(requester, success = false)
  }
}