gpt4 book ai didi

scala - 按需 Actor 获取或创建

转载 作者:行者123 更新时间:2023-12-03 11:24:11 26 4
gpt4 key购买 nike

我可以用 actorOf 创建 Actor 并用 actorFor 查看它们.我现在想找个 Actor id:String如果它不存在,我希望它被创建。像这样的东西:

  def getRCActor(id: String):ActorRef = {
Logger.info("getting actor %s".format(id))
var a = system.actorFor(id)
if(a.isTerminated){
Logger.info("actor is terminated, creating new one")
return system.actorOf(Props[RC], id:String)
}else{
return a
}
}

但这不适用于 isTerminated总是正确的,我得到 actor name 1 is not unique!第二次通话异常(exception)。我想我在这里使用了错误的模式。有人可以帮助如何实现这一目标吗?我需要
  • 按需创建 Actor
  • 按 id 查找 Actor ,如果不存在则创建他们
  • 破坏的能力,因为我不知道我是否会再次需要它

  • 我应该为此使用调度程序还是路由器?

    解决方案
    正如提议的那样,我使用了一个具体的主管,将可用的 Actor 保存在 map 中。可以要求提供他的一个 child 。
    class RCSupervisor extends Actor {

    implicit val timeout = Timeout(1 second)
    var as = Map.empty[String, ActorRef]

    def getRCActor(id: String) = as get id getOrElse {
    val c = context actorOf Props[RC]
    as += id -> c
    context watch c
    Logger.info("created actor")
    c
    }

    def receive = {

    case Find(id) => {
    sender ! getRCActor(id)
    }

    case Terminated(ref) => {
    Logger.info("actor terminated")
    as = as filterNot { case (_, v) => v == ref }
    }
    }
    }

    他的同伴对象
    object RCSupervisor {

    // this is specific to Playframework (Play's default actor system)
    var supervisor = Akka.system.actorOf(Props[RCSupervisor])

    implicit val timeout = Timeout(1 second)

    def findA(id: String): ActorRef = {
    val f = (supervisor ? Find(id))
    Await.result(f, timeout.duration).asInstanceOf[ActorRef]
    }
    ...
    }

    最佳答案

    我基于 oxbow_lakes 的代码/建议来解决这个问题,但我没有创建所有子角色的简单集合,而是使用(双向) map ,如果子角色的数量很大,这可能是有益的。

    import play.api._
    import akka.actor._
    import scala.collection.mutable.Map

    trait ResponsibleActor[K] extends Actor {
    val keyActorRefMap: Map[K, ActorRef] = Map[K, ActorRef]()
    val actorRefKeyMap: Map[ActorRef, K] = Map[ActorRef, K]()

    def getOrCreateActor(key: K, props: => Props, name: => String): ActorRef = {
    keyActorRefMap get key match {
    case Some(ar) => ar
    case None => {
    val newRef: ActorRef = context.actorOf(props, name)
    //newRef shouldn't be present in the map already (if the key is different)
    actorRefKeyMap get newRef match{
    case Some(x) => throw new Exception{}
    case None =>
    }
    keyActorRefMap += Tuple2(key, newRef)
    actorRefKeyMap += Tuple2(newRef, key)
    newRef
    }
    }
    }

    def getOrCreateActorSimple(key: K, props: => Props): ActorRef = getOrCreateActor(key, props, key.toString)

    /**
    * method analogous to Actor's receive. Any subclasses should implement this method to handle all messages
    * except for the Terminate(ref) message passed from children
    */
    def responsibleReceive: Receive

    def receive: Receive = {
    case Terminated(ref) => {
    //removing both key and actor ref from both maps
    val pr: Option[Tuple2[K, ActorRef]] = for{
    key <- actorRefKeyMap.get(ref)
    reref <- keyActorRefMap.get(key)
    } yield (key, reref)

    pr match {
    case None => //error
    case Some((key, reref)) => {
    actorRefKeyMap -= ref
    keyActorRefMap -= key
    }
    }
    }
    case sth => responsibleReceive(sth)
    }
    }

    要使用从 ResponsibleActor 继承的功能并实现 responsibleReceive .注意:此代码尚未经过彻底测试,可能仍有一些问题。我省略了一些错误处理以提高可读性。

    关于scala - 按需 Actor 获取或创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10766187/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com