我是akka的新手,可以用一些帮助来解决这个问题,如果我用错误的名字打电话,请原谅我。我有一个json文档需要根据特定字段是否为真来转到两个接收器之一。我已经能够使用以下方式向各个单一消费者发布:
[{"item":"foo","category_id":1},{"item":"bar","category_id":2},[3]]
我尝试插入这样的条件语句:
Source(publisher).map{cmd =>
println("****************** Pick up message"+cmd)
val cmdAst = cmd.toString.parseJson
cmdAst.convertTo[FormAdded]
}.runWith(Sink.actorSubscriber(ProcessorActor.props))
所有内容都编译并运行没有错误,但是当提交表单时,它永远不会被提取并且只是超时。
我还试图通过以下方式直接将用户吸收到相同的结果:
var actorSubscriber = ProcessorActor.props
Source(publisher).map { cmd =>
println("****************** Pick up message" + cmd)
val cmdAst = cmd.toString.parseJson
cmdAst.convertTo[FormAdded]
if (cmdAst.convertTo[FormAdded].toLocation.toString().equalsIgnoreCase("Main")) {
actorSubscriber = EventActor.props
} else actorSubscriber = ProcessorActor.props
}.runWith(Sink.actorSubscriber(actorSubscriber))
谢谢
答案 0 :(得分:3)
这可以使用Graph
使用Broadcast
和两个不同的接收器来完成。下面是一个使用Source
整数并将它们分成两个不同的接收器的示例,一个用于均衡,一个用于赔率。
import scala.concurrent.duration._
import akka.stream.scaladsl.{Source, Sink, Flow, FlowGraph, Broadcast, Merge}
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
object TwoSinks extends App {
implicit val actorSystem = ActorSystem()
implicit val materializer = ActorMaterializer()
FlowGraph.closed() { implicit builder: FlowGraph.Builder[Unit] =>
import FlowGraph.Implicits._
val source = Source(1 to 10)
//beam splitter
val bcast = builder.add(Broadcast[Int](2))
def isEven(i : Int) = i % 2 == 0
val evenFilter = Flow[Int].filter(isEven)
val oddFilter = Flow[Int].filter(!isEven(_))
val evenSink = Sink.foreach[Int](i => println(s"evenSink received : $i"))
val oddSink = Sink.foreach[Int](i => println(s" oddSink received : $i"))
source ~> bcast ~> evenFilter ~> evenSink
bcast ~> oddFilter ~> oddSink
}.run()
import actorSystem.dispatcher
actorSystem.scheduler.scheduleOnce(10 seconds){actorSystem.shutdown()}
}//end object TwoSinks
您可以轻松扩展此示例以使用在您的接收器中使用Actors而不是println的Sink.actorSubscriber
。使用您的特定代码:
FlowGraph.closed() {implicit builder: FlowGraph.Builder[Unit] =>
import FlowGraph.Implicits._
def pickupMsg(cmd : String) =
{println(s"****************** Pick up message: $cmd") ; cmd}
//I don't know the type of cmdAst so I'm using "CmdAstType"
type CmdAstType = ???
def convert(cmd : String) : CmdAstType = {
val cmdAst = cmd.toString.parseJson
cmdAst.convertTo[FormAdded]
cmdAst
}//end def convert
val source = Source(publisher).map(pickupMsg).map(convert)
def isEvent(cmdAst : CmdAstType) : Boolean = cmdAst.convertTo[FormAdded]
.toLocation
.toString()
.equalsIgnoreCase("Main")
val eventFilter = Flow[CmdAstType].filter(isEvent)
val processorFilter = Flow[CmdAstType].filter(!isEvent(_))
val eventSink = Sink.actorSubscriber[CmdAstType](EventActor.props)
val processorSink = Sink.actorSubscriber[CmdAstType](ProcessorActor.props)
val bcast = builder.add(Broadcast[CmdAstType](2))
source ~> bcast ~> eventFilter ~> eventSink
bcast ~> processorFilter ~> processorSink
}//end FlowGraph.closed()
答案 1 :(得分:2)
你不能让Sink依赖于元素:流程已经存在并且在它运行之前包含固定的Source
和Sink
并且开始从源获取元素(有{ {3}}但他们都没有做你想要的事情。
你可以做的是有一个Sink
,它会根据元素将收到的元素转发给不同的actor。例如。您可以撰写DispatchActor
来查看收到的邮件,并将其发送到EventActor
或ProcessorActor
,并将其与Sink.actorSubscriber(DispatchActor.props)
一起使用。