Классы актеров должны расширяться Actor
вместо ActorRef
.Также используйте ActorRef
для ссылки на актера.Следовательно, DeviceManager
следует определить следующим образом:
class DeviceManager(dlc: ActorRef) extends Actor {
// ...
}
Идея заключается в том, что вы будете использовать ActorRef
актера DeadLetterChannel
при создании актеров устройства.Например:
val dlc: ActorRef = context.actorOf(/* .. */)
val device1: ActorRef = context.actorOf(Props(classOf[DeviceManager], dlc)
val device2: ActorRef = context.actorOf(Props(classOf[DeviceManager], dlc)
Затем вы можете сделать так, как предложил Тим в своем ответе, захватить случай по умолчанию в блоке receive
и отправить это сообщение на dlc
:
class DeviceManager(dlc: ActorRef) extends Actor {
def receive = {
/* other case clauses */
case msg =>
dlc ! msg
}
}
Кроме того, вместо передачи изменяемой очереди в DeadLetterChannel
в качестве аргумента конструктора, инкапсулируйте это состояние внутри субъекта в виде неизменяемой очереди и выставляйте его только через передачу сообщений:
class DeadLetterChannel extends Actor with akka.actor.ActorLogging {
var queue = collection.immutable.Queue[Any](0)
def receive = {
case GetMessages => // GetMessages is a custom case object
sender() ! queue
case msg =>
val s = sender()
log.info(s"DLC just received the following message from [$s]: $msg")
queue = queue.enqueue(msg)
}
}
Другой подходзаключается в том, чтобы не определять регистр по умолчанию (т. е. пропустить предложение case msg =>
) и использовать механизмы Akka для работы с необработанными сообщениями.Ниже приведены несколько параметров:
Включить встроенную запись для необработанных сообщений , которая регистрирует эти сообщения на уровне отладки:
akka {
actor {
debug {
# enable DEBUG logging of unhandled messages
unhandled = on
}
}
}
Этот подход, пожалуй, самый простой, если вы просто хотите регистрировать необработанные сообщения.
Как указано в документации :
Если текущее поведение актера не соответствует полученному сообщению ... по умолчанию публикует akka.actor.UnhandledMessage(message, sender, recipient)
в потоке событий системы актера.
В свете этого вы можете создать актера, который подписывается напоток событий и обрабатывает akka.actor.UnhandledMessage
сообщений.Такой актер может выглядеть следующим образом:
import akka.actor.{ Actor, UnhandledMessage, Props }
class UnhandledMessageListener extends Actor {
def receive = {
case UnhandledMessage(msg, sender, recipient) =>
// do something with the message, such as log it and/or something else
}
}
val listener = system.actorOf(Props[UnhandledMessageListener])
system.eventStream.subscribe(listener, classOf[UnhandledMessage])
Более подробную информацию о потоке событий и создании подписчика на этот поток можно найти здесь .