2014-09-16 2 views

ответ

12

This reply by Roland Kuhn предполагает, что это не совсем тривиальная проблема, но вы можете получить довольно близко (для актеров, которые будут отвечать на сообщения в разумные сроки), используя протокол запроса-ответа , который все участники подчиниться.

Некоторые непроверенный код выброшены вместе, чтобы проиллюстрировать идею:

import akka.actor._ 

class IdentifyingActor extends Actor with ActorLogging { 

    def receive = { 

    case 'start => 
     self ! ActorPath.fromString("/user") 

    case path: ActorPath => 
     context.actorSelection(path/"*") ! Identify(()) 

    case ActorIdentity(_, Some(ref)) => 
     log.info(ref.path) 
     self ! ref.path 
} 
2

По the documentation вы можете использовать ActorSelection с групповым символом *, чтобы актеры отправить идентификации сообщений. У вас может быть актер, который собирает ActorRef с.

Как упоминалось в @ chris-martin, только те, кто в данный момент не занят, отправят. Очень простой актер:

// make all the available actor to send an identifying message 
public void freeActors() 
{ 
    ActorSelection selection = 
    getContext().actorSelection("/user/*"); 
    selection.tell(new Identify(identifyId), getSelf()); 
} 

... 
// collect responses 
@Override 
public void onReceive(Object message) { 
    if (message instanceof ActorIdentity) { 
    ActorIdentity identity = (ActorIdentity) message; 
    // get the ref of the sender 
    ActorRef ref = identity.getRef(); 
    // the sender is up and available 
    ... 

EDIT: Я знаю, что это для Java, но мне это показалось полезным.

3

ActorSystem имеет приватный метод printTree, который вы можете использовать для отладки.

1) Закрытый метод вызывающего абонента (из https://gist.github.com/jorgeortiz85/908035):

class PrivateMethodCaller(x: AnyRef, methodName: String) { 
    def apply(_args: Any*): Any = { 
    val args = _args.map(_.asInstanceOf[AnyRef]) 

    def _parents: Stream[Class[_]] = Stream(x.getClass) #::: _parents.map(_.getSuperclass) 

    val parents = _parents.takeWhile(_ != null).toList 
    val methods = parents.flatMap(_.getDeclaredMethods) 
    val method = methods.find(_.getName == methodName).getOrElse(throw new IllegalArgumentException("Method " + methodName + " not found")) 
    method.setAccessible(true) 
    method.invoke(x, args: _*) 
    } 
} 

class PrivateMethodExposer(x: AnyRef) { 
    def apply(method: scala.Symbol): PrivateMethodCaller = new PrivateMethodCaller(x, method.name) 
} 

2) Использование

val res = new PrivateMethodExposer(system)('printTree)() 
println(res) 

Напечатает:

->/LocalActorRefProvider$$anon$1 class akka.actor.LocalActorRefProvider$Guardian status=0 2 children 
    ⌊-> system LocalActorRef class akka.actor.LocalActorRefProvider$SystemGuardian status=0 3 children 
    | ⌊-> deadLetterListener RepointableActorRef class akka.event.DeadLetterListener status=0 no children 
    | ⌊-> eventStreamUnsubscriber-1 RepointableActorRef class akka.event.EventStreamUnsubscriber status=0 no children 
    | ⌊-> log1-Logging$DefaultLogger RepointableActorRef class akka.event.Logging$DefaultLogger status=0 no children 
    ⌊-> user LocalActorRef class akka.actor.LocalActorRefProvider$Guardian status=0 1 children 
... 

Осторожно, это может привести к OOM Если у вас есть много актеров.

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