У меня есть сложная проблема при попытке изменить состояние дочернего актера с помощью метода become
. Я реализовал наследование актера в соответствии с чертой Receiving
, предложенной здесь:
trait Mcma extends Receiving with ActorLogging {
val actorName: String
/**
* Simple method to be overridden when necessary
* @param entity the response entity
*/
protected def handleHttpOK(entity: ResponseEntity): Unit = log.info(s"$actorName got unhandled OK response")
// Add http responses match if necessary
receiver {
case HttpResponse(StatusCodes.OK, _, entity, _) => handleHttpOK(entity)
case resp @ HttpResponse(code, _, _, _) =>
log.error(s"$actorName got response code: {}", code)
// Discard the flow to avoid backpressure
resp.discardEntityBytes()
case e: Status.Failure => log.error(s"$actorName got failure: {}", e.cause.getMessage)
case _ => log.warning(s"Unexpected message in $actorName")
}
}
Проблема возникает, когда у меня есть актор, который реализует этот признак Mcma
и меняет свое состояние с помощью шаблона become
:
class Reseau(url: String, optSender: Option[ActorRef]) extends Mcma with Receiving {
override val actorName: String = "ReseauActor"
/**
* The active method used to handle actor state change with the become helper
* @param queryDataStr the query string for each call to ReseauActor
* @return
*/
def active(queryDataStr: String): Receive = {
case s: String => context become active(s)
}
// Init the actor with empty query
receiver(
active("")
)
}
После изменения контекста унаследованные случаи сопоставления по умолчанию, такие как e
или _
, больше не сопоставляются. Скорее всего проблема очевидна...
[Обновленная рабочая версия с ответом от Евгения] С упомянутой чертой Receiving
актер Reseau становится
class Reseau(url: String, optSender: Option[ActorRef]) extends Mcma {
override val actorName: String = "ReseauActor"
override def preStart(): Unit = {
super.preStart()
// Init the actor with empty query
context become receiver(active(""))
}
/**
* The active method used to handle actor state change with the become helper
*
* @param queryDataStr the query string for each call to ReseauActor
* @return
*/
def active(queryDataStr: String): Receive = {
case s: String => context become receiver(active(s))
}
}
и черта Mcma
:
trait Mcma extends Receiving with ActorLogging {
val actorName: String
/**
* Simple method to be overridden when necessary
* @param entity the response entity
*/
protected def handleHttpOK(entity: ResponseEntity): Unit = log.info(s"$actorName got unhandled OK response")
// For http response handling
final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))
override def preStart(): Unit = log.info(s"$actorName started")
override def postStop(): Unit = log.info(s"$actorName stopped")
// Add http responses match if necessary
addReceiver {
case HttpResponse(StatusCodes.OK, _, entity, _) => handleHttpOK(entity)
case resp @ HttpResponse(code, _, _, _) =>
log.error(s"$actorName got response code: {}", code)
// Discard the flow to avoid backpressure
resp.discardEntityBytes()
case e: Status.Failure => log.error(s"$actorName got failure: {}", e.cause.getMessage)
case _ => log.warning(s"Unexpected message in $actorName")
}
}
и для того, чтобы определить актера, которому не нужно было бы менять свое внутреннее состояние, вы просто сделали бы:
class TLRVJob1() extends Mcma {
override val actorName: String = "TLRVJob1Actor"
addReceiver {
case t: Get => ???
}
}