akka actor текущее имя функции приема
У меня есть простой актер с 2 поведением
package com.hello
import akka.actor.{Actor, ActorLogging}
case object Ping
class Hello extends Actor with ActorLogging {
import context._
def receive: Receive = behaviorFoo
self ! Ping
def behaviorFoo: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
become(behaviorBar)
self ! Ping
}
def behaviorBar: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
}
}
эту вещь делают те:
пинг себя
регистрация текущей функции приема
изменить поведение на поведение Bar
пинг себя
регистрация текущей функции приема
в обоих случаях записывается "$ anonfun $ поведение Foo$1"
почему это не "$ anonfun $ поведение Bar$1" во втором журнале?
если я поменяю код на
self ! Ping
def receive: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
become(behaviorFoo)
self ! Ping
}
def behaviorFoo: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
become(behaviorBar)
self ! Ping
}
def behaviorBar: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
}
он записывает 3 раза "$ anonfun $ получает $ 1"
существует ли какой-либо способ получить текущее поведение (получить) имя функции? или мне нужно в любое время напечатать как log.info("поведение Foo")?
Обновить:
для регистрации проблем, я добавил
trait MyLogging extends ActorLogging {
this: Actor ⇒
private[this] val actorClassName = this.getClass.getSimpleName
private[this] var receiveName: String = {
val receiveClassName = s"${this.receive.getClass.getSimpleName}"
val left = receiveClassName.substring(0, receiveClassName.lastIndexOf("$"))
left.substring(left.lastIndexOf("$") + 1)
}
def become(behavior: Actor.Receive): Unit = {
val behaviorClassName = behavior.getClass.getSimpleName
val left = behaviorClassName.substring(0, behaviorClassName.lastIndexOf("$"))
receiveName = left.substring(left.lastIndexOf("$") + 1)
context.become(behavior)
}
def info(message: Any): Unit = log.info(s"$actorClassName : $receiveName got $message")
}
тогда мой код актера станет
class Hello extends Actor with MyLogging {
def receive: Receive = behaviorFoo
self ! Ping
def behaviorFoo: Receive = {
case any =>
info(any)
become(behaviorBar)
self ! Ping
}
def behaviorBar: Receive = {
case any => info(any)
}
}
теперь логи выглядят как
... Привет
... Привет: поведение Bar получил Ping
1 ответ
Может быть, поэтому они называются анонимными функциями. behaviorFoo
, behaviorBar
... имена не влияют на эти анонимные функции. Чтобы проиллюстрировать это, рассмотрим это:
// this is a val!
val behaviorFoo: Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
become(behaviorBar)
self ! Ping
}
// this returns the same anonymous function
def behaviorFoo2 = behaviorFoo
С учетом вышесказанного вы должны увидеть, что имя, под которым вы храните анонимную функцию, не имеет ничего общего с самой анонимной функцией...
Теперь, если вы понимаете, что это за анонимные функции (это частичные функции с псевдонимом типа Actor.Receive
) вы можете сделать что-то вроде ниже:
// not an anonymous function anymore
class BehaviourFoo extends Actor.Receive {
val anonymousFun: Actor.Receive = {
case _ =>
log.info(this.receive.getClass.getSimpleName)
become(behaviorBar)
self ! Ping
}
override def isDefinedAt(x: Any) = anonymousFun.isDefinedAt(x)
override def apply(x: Any) = anonymousFun(x)
}
// again, the name behaviorFoo doesn't matter
def behaviorFoo: Receive = new BehaviourFoo
Это, конечно, не стоит хлопот, но это должно помочь вам понять, что происходит.