我正在研究Akka EventBus以检查它是否可以解决我的一个设计问题而且我仍然不知道。 问题如下。
简化,我有:
case class Request(requesterId: String, operation: String, header: RequestHeader)
case class Response(requesterId: String, operation: String, header: ResponseHeader)
我有几个具有不同功能的演员,我希望某个演员根据Response
订阅requesterId
,其他一些则取决于operation
。
有没有办法通过EventBus和分类器轻松实现这一目标?
谢谢, 乔尔
答案 0 :(得分:0)
当然,它被称为LookupEventBus。您可以通过扩展它来实现自己的总线,并在requesterId
方法中提取classify
,如下所示:
class LookupBusImpl extends EventBus with LookupClassification {
type Event = HasRequesterId // I made up a super type for you here
type Classifier = String
type Subscriber = ActorRef
override def classify(event: HasRequesterId): String = event.requesterId
然后您订阅了给定的requesterId
,如下所示:
lookupBus.subscribe(actorRef, "requester-100")
然后,此Actor将只收到已被归类为requester-100
的消息。
答案 1 :(得分:0)
我同意Konrad的意见,您应该实施新的LookupClassification
公交车来解决您的问题。我认为最简单的是有两个单独的这些总线实例,一个按requestterId分类,另一个按操作分类。这种方法的一些基本设置工作是:
//Singleton to hold the instances of each stream type
object ResponseEventStream{
val RequestorIdStream = new RequestorIdResponseEventStream
val OperationStream = new OperationResponseEventStream
}
//Common functionality for the two different types of streams
trait ResponseEventStream extends ActorEventBus with LookupClassification{
import ResponseEventStream._
type Event = Response
type Classifier = String
protected def mapSize = 128
protected def publish(resp:Response, subscriber: ActorRef) = {
if (subscriber.isTerminated) unsubscribe(subscriber)
else subscriber ! resp
}
}
//Concrete impl that uses requesterId to classify
class RequestorIdResponseEventStream extends ResponseEventStream{
protected def classify(resp:Response) = resp.requesterId
}
//Concrete impl that uses operation to classify
class OperationResponseEventStream extends ResponseEventStream{
protected def classify(resp:Response) = resp.operation
}
//Trait to mix into classes that need to publish or subscribe to response events
//Has helper methods to simplify interaction with the two distinct streams
trait ResponseEventing{
import ResponseEventStream._
def publishResponse(resp:Response){
RequestorIdStream.publish(resp)
OperationStream.publish(resp)
}
def subscribeByRequestId(requestId:String, ref:ActorRef){
RequestorIdStream.subscribe(ref, requestId)
}
def subscribeByOperartion(op:String, ref:ActorRef){
OperationStream.subscribe(ref, op)
}
}
然后你只需要将ResponseEventing
特征混合到需要发布Response
事件或需要订阅它们的actor的actor中。正在发布的演员将调用publishResponse
,需要订阅的演员将调用subscribeXXX
,具体取决于他们感兴趣的分类(requesterId或操作)。