Scala Akka参与者继承与context.been
在尝试使用Scala Akka参与者继承与context.been,scala,akka,typesafe,Scala,Akka,Typesafe,在尝试使用been方法更改儿童演员的状态时,我遇到了一个棘手的问题。我根据建议的接收特征实现了参与者继承: 当我有一个参与者实现了这个Mcma特性,并使用been模式更改了自己的状态时,就会出现问题: class Reseau(url: String, optSender: Option[ActorRef]) extends Mcma with Receiving { override val actorName: String = "ReseauActor" /** * Th
been
方法更改儿童演员的状态时,我遇到了一个棘手的问题。我根据建议的接收
特征实现了参与者继承:
当我有一个参与者实现了这个Mcma
特性,并使用been
模式更改了自己的状态时,就会出现问题:
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
或\u
将不再匹配。很可能有一个明显的问题
[更新的工作版本,带有Evgeny的答案]
具有所述的接收
特征,
重新设计演员成为
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))
}
}
以及Mcmatrait:
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")
}
}
trait Receiving extends Actor {
var receivers: Receive = Actor.emptyBehavior
def addReceiver(next: Actor.Receive): Unit = {receivers = receiver(next)}
def receiver(next: Actor.Receive): Receive = {receivers orElse next}
def receive: Receive = receivers
}
为了定义一个无需改变其内部状态的参与者,您只需执行以下操作:
class TLRVJob1() extends Mcma {
override val actorName: String = "TLRVJob1Actor"
addReceiver {
case t: Get => ???
}
}
在这种情况下,最简单的解决方法可能是放弃使用
变成。也就是说,不要将queryDataStr
状态编码为参数,而是将queryDataStr
更改为var
:
class Reseau(url: String, optSender: Option[ActorRef]) extends Mcma with Receiving {
override val actorName: String = "ReseauActor"
var queryDataStr: Option[String] = None
receiver {
case s: String => queryDataStr = Option(s)
}
}
我建议修改初始接收
特征:
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")
}
}
trait Receiving extends Actor {
var receivers: Receive = Actor.emptyBehavior
def addReceiver(next: Actor.Receive): Unit = {receivers = receiver(next)}
def receiver(next: Actor.Receive): Receive = {receivers orElse next}
def receive: Receive = receivers
}
现在,您有两种情况,添加receive的永久部分和been的类依赖部分。在层次结构中使用addReceiver
更改receiver
,并初始化Reseau
类:而不是
receiver(
active("")
)
将其移动到启动前
,格式如下:
override def preStart(): Unit = {
super.preStart()
context become receiver(active(""))
}
并将active
methodbody更改为
context become receiver(active(s))
是的,我确实想到了这个解决方案,但更愿意尝试保持功能状态更改方法。