2013-02-11 2 views
0

В моем приложении есть сингл-актерская система, и это отлично работает, за исключением того, что когда одно и то же приложение загружается и выгружается внутри одной JVM для тестирования, у меня есть ошибка, потому что я попробуйте в моей процедуре запуска воссоздать действующего актера.Как управлять отключением актера в одноэлементном режиме ActorSystem

В результате я получаю akka.actor.InvalidActorNameException, потому что имя Актера не уникально.

Я ищу способ плавного отключения актеров в зависимости от актерских систем без отключения самой системы актеров. Какая разумная стратегия для этого?

+1

Вы проверили http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html#Stopping_actors? –

+0

Для этого вам необходимо следить за всеми участниками этой системы. Я искал автоматическое решение – Edmondo1984

+0

Ну, не совсем. Из-за иерархической организации Akka вам нужно следить только за актерами верхнего уровня, которые, как я предполагаю, немногочисленны. –

ответ

0

Вы хотите что-то подобное?

object AkkaTest extends App { 
    import akka.actor._ 
    import akka.pattern.ask 
    import akka.util.Timeout 
    import scala.concurrent.duration._ 

    val system = ActorSystem.create 

    val supervisor = system.actorOf(Props[MasterOfPuppets], name = "masterOfPuppets") 

    private object AllTerminated 

    private class MasterOfPuppets extends Actor { 

    var supervised = 0 

    var waiterForTerminated: Option[ActorRef] = None 

    def receive = { 
     case actor: ActorRef => 
     context.watch(actor) 
     supervised += 1 
     case Terminated(dead) => 
     supervised -= 1 
     if (supervised == 0) { 
      waiterForTerminated.map(_ ! AllTerminated) 
      waiterForTerminated = None 
     } 
     case AllTerminated => 
     if (supervised == 0) { 
      sender ! AllTerminated 
     } else { 
      waiterForTerminated = Some(sender) 
     } 
    } 
    } 

    private class TestedActor extends Actor { 
    def receive = { 
     case a: Any => sender ! a 
    } 
    } 

    implicit val timeout = Timeout(5.seconds) // needed for `?` below 

    // Create first actor 
    val actor1 = system.actorOf(Props[TestedActor], name = "name1") 
    supervisor ! actor1 
    actor1 ! PoisonPill 

    val waitForIt = supervisor ? AllTerminated 
    Await.result(waitForIt, 5.seconds) 
    // Same name 
    val actor2 = system.actorOf(Props[TestedActor], name = "name1") 
    supervisor ! actor2 

    println("ok then") 
} 

Ваша проблема очень проста: Akka и сообщение асинхронны. Если вы попытаетесь создать актера сразу после его убийства, имя не будет доступно. Попробуйте просто Thread.sleep перед созданием нового актера, и он будет работать .. :)

+2

Нет, ты не спишь. вы используете Death Watch и создаете нового актера, как только получите сообщение Terminated-message. –

1

Это не точно ответить на ваш вопрос - «... таким образом, чтобы плавно выключение актеров ...», но вы упомянули, что вы можете запустить два приложения в одном JVM.

Не могли бы вы сделать свою актерскую систему singleton в приложении экземпляра вместо singleton в целом JVM?

У вас будет две независимые актерские системы, у вас не будет конфликтов имен и не будет необходимости запускать/останавливать определенных участников.

Я думаю, проблемы могут быть, если некоторые из участников взаимодействуют с внешним миром, например, потребляя некоторые сообщения от JMS и т. Д. Тогда не будет очевидно, какая актерская система их обрабатывает.

Смежные вопросы