vis*_*shr 5 scala implicit implicit-conversion actor akka
我想在协作actor的系统中隐式地传播请求上下文.
为了简化和呈现这种情况,我的系统有多个actor,传递给这些actor的消息需要包含这个RequestContext对象.
ActorA接收MessageA类型的消息,ActorB接收MessageB类型的消息
当ActorA需要向ActorB发送消息时,作为MessageA处理的一部分,它执行业务逻辑,然后根据逻辑结果以及MessageA中可用的RequestContext构造MessageB,然后将其发送给ActorB
def handle(ma:MessageA) {
val intermediateResult = businessLogic(ma)
actorB ! MessageB(intermediateResult, ma.requestContext)
}
Run Code Online (Sandbox Code Playgroud)
我们有一大堆要处理的消息,并且明确地传递requestContext是很麻烦的.
我正在尝试使用Scala的implicits功能创建方法,以避免将传入消息中嵌入的RequestContext显式注入传出消息.
消息是案例类(它们需要).我已经阅读了有关implicits规则的内容,但是将对象的属性带入当前的隐式范围似乎很牵强.
我相信这应该是一个共同的要求.有什么建议 ?
谢谢.
在您的示例中,您对有问题的消息的处理已经被分解为一个方法,这使得这个直截了当:
trait RequestContext
case class MessageA(req: RequestA, ctx: RequestContext)
object MessageA {
def apply(req: RequestA)(implicit ctx: RequestContext) = MessageA(req, ctx)
}
case class MessageB(req: RequestB, ctx: RequestContext)
object MessageB {
def apply(req: RequestB)(implicit ctx: RequestContext) = MessageB(req, ctx)
}
class Example extends Actor {
def receive = {
case MessageA(req, ctx) => handle(req)(ctx)
}
def handle(req: RequestA)(implicit ctx: RequestContext): Unit = {
val intermediateResult = businessLogic(req) // could take implicit ctx as well
actorB ! MessageB(intermediateResult)
}
}
Run Code Online (Sandbox Code Playgroud)
但正如您所看到的,在声明消息类型时仍然存在一些开销,并且handle方法的签名也需要更改.这种方案是否值得,取决于这些隐含价值的消费者和生产者之间的比例(即,如果handle使用上下文不止一件事,那就更有意义).
上述的变体可以是:
case class MessageA(req: RequestA, ctx: RequestContext)
object MessageA {
def apply(req: RequestA)(implicit ctx: RequestContext) = MessageA(req, ctx)
implicit def toContext(implicit msg: MessageA) = msg.ctx
}
case class MessageB(req: RequestB, ctx: RequestContext)
object MessageB {
def apply(req: RequestB)(implicit ctx: RequestContext) = MessageB(req, ctx)
implicit def toContext(implicit msg: MessageB) = msg.ctx
}
...
def handle(implicit ma: MessageA): Unit = {
val intermediateResult = businessLogic(req)
actorB ! MessageB(intermediateResult)
}
Run Code Online (Sandbox Code Playgroud)
在我看来,最简单的方法是使你的val隐含在case类中.
case class MessageA(req: RequestA)(implicit val ctx: RequestContext)
case class MessageB(req: RequestB)(implicit val ctx: RequestContext)
def businessLogic(req:RequestA):RequestB
def handle(ma: MessageA): Unit = {
// import all the members of ma so that there is a legal implicit RequestContext in scope
import ma._
val intermediateResult = businessLogic(req)
actorB ! MessageB(intermediateResult)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2861 次 |
| 最近记录: |