Akka Streams scala DSL和Op Rabbit
我已经开始使用Akka Streams和Op Rabbit,我有点困惑 我需要基于谓词分割流,然后将它们组合起来,就像我在创建图和使用分区和合并时所做的那样 我已经能够使用GraphDSL.Builder做类似的事情,但似乎无法让它与AckedSource/Flow/Sink一起工作 该图如下所示:Akka Streams scala DSL和Op Rabbit,scala,rabbitmq,akka-stream,Scala,Rabbitmq,Akka Stream,我已经开始使用Akka Streams和Op Rabbit,我有点困惑 我需要基于谓词分割流,然后将它们组合起来,就像我在创建图和使用分区和合并时所做的那样 我已经能够使用GraphDSL.Builder做类似的事情,但似乎无法让它与AckedSource/Flow/Sink一起工作 该图如下所示: | --> flow1 --> | source--> partition --> | | --&
| --> flow1 --> |
source--> partition --> | | --> flow3 --> sink
| --> flow2 --> |
我不确定splitWhen是否是我应该使用的,因为我总是需要正好两个流
这是一个不进行分区且不使用GraphDSL.Builder的示例:
def splitExample(source: AckedSource[String, SubscriptionRef],
queueName: String)
(implicit actorSystem: ActorSystem): RunnableGraph[SubscriptionRef] = {
val toStringFlow: Flow[AckTup[Message], AckTup[String], NotUsed] = Flow[AckTup[Message]]
.map[AckTup[String]](tup => {
val (p,m) = tup
(p, new String(m.data))
})
val printFlow1: Flow[AckTup[String], AckTup[String], NotUsed] = Flow[AckTup[String]]
.map[AckTup[String]](tup => {
val (p, s) = tup
println(s"flow1 processing $s")
tup
})
val printFlow2: Flow[AckTup[String], AckTup[String], NotUsed] = Flow[AckTup[String]]
.map[AckTup[String]](tup => {
val (p, s) = tup
println(s"flow2 processing $s")
tup
})
source
.map(Message.queue(_, queueName))
.via(AckedFlow(toStringFlow))
// partition if string.length < 10
.via(AckedFlow(printFlow1))
.via(AckedFlow(printFlow2))
.to(AckedSink.ack)
}
}}
编译器无法解析~>
运算符
因此,我的问题是:
在处理问题时,请记住以下定义
AckedSource[Out,Mat]
是Source[AckTup[Out],Mat]]
AckedFlow[In,Out,Mat]
是Flow[AckTup[In],AckTup[Out],Mat]
AckedSink[In,Mat]
是Sink[AckTup[In],Mat]
AckTup[T]
是(Promise[Unit],T)
AckTup的T
部分操作
.acked
组合器将完成AckedFlow的承诺[单元]
~>
)将适用于一组Akka预定义形状(请参见代码),但它不适用于由确认流库定义的自定义形状
你有两条出路:
GraphDSL.Implicits
.wrappedRepr
-在AckedSource
、AckedFlow
和AckedSink
上访问已包装的阶段根据Stefano Bonetti出色的指导,这里有一个可能的解决方案:
graph:
|--> short --|
rabbitMq --> before --| |--> after
|--> long --|
解决方案:
graph:
|--> short --|
rabbitMq --> before --| |--> after
|--> long --|
val before: Flow[AckTup[Message], AckTup[String], NotUsed] = Flow[AckTup[Message]].map[AckTup[String]](tup => {
val (p,m) = tup
(p, new String(m.data))
})
val short: Flow[AckTup[String], AckTup[String], NotUsed] = Flow[AckTup[String]].map[AckTup[String]](tup => {
val (p, s) = tup
println(s"short: $s")
tup
})
val long: Flow[AckTup[String], AckTup[String], NotUsed] = Flow[AckTup[String]].map[AckTup[String]](tup => {
val (p, s) = tup
println(s"long: $s")
tup
})
val after: Flow[AckTup[String], AckTup[String], NotUsed] = Flow[AckTup[String]].map[AckTup[String]](tup => {
val (p, s) = tup
println(s"all $s")
tup
})
def buildSplitGraph(source: AckedSource[String, SubscriptionRef]
, queueName: String
, splitLength: Int)(implicit actorSystem: ActorSystem): Graph[ClosedShape, Future[Done]] = {
GraphDSL.create(Sink.ignore) { implicit builder: GraphDSL.Builder[Future[Done]] => s =>
val toShort = 0
val toLong = 1
// junctions
val split = builder.add(Partition[AckTup[String]](2, (tup: AckTup[String]) => {
val (p, s) = tup
if (s.length < splitLength) toShort else toLong
}
))
val merge = builder.add(Merge[AckTup[String]](2))
//graph
val beforeSplit = source.map(Message.queue(_, queueName)).wrappedRepr ~> AckedFlow(before).wrappedRepr
beforeSplit ~> split
// must do short, then long since the split goes in that order
split ~> AckedFlow(short).wrappedRepr ~> merge
split ~> AckedFlow(long).wrappedRepr ~> merge
// after the last AckedFlow, be sure to '.acked' so that the message will be removed from the queue
merge ~> AckedFlow(after).acked ~> s
ClosedShape
}}
val-before:Flow[AckTup[Message],AckTup[String],NotUsed]=Flow[AckTup[Message].map[AckTup[String]](tup=>{
val(p,m)=tup
(p,新字符串(m.data))
})
val short:Flow[AckTup[String],AckTup[String],NotUsed]=Flow[AckTup[String]].map[AckTup[String]](tup=>{
val(p,s)=tup
println(s“short:$s”)
塔普
})
val long:Flow[AckTup[String],AckTup[String],NotUsed]=Flow[AckTup[String]].map[AckTup[String]](tup=>{
val(p,s)=tup
println(s“长:$s”)
塔普
})
val after:Flow[AckTup[String],AckTup[String],NotUsed]=Flow[AckTup[String]].map[AckTup[String]](tup=>{
val(p,s)=tup
println(s“全部$s”)
塔普
})
def buildSplitGraph(源代码:AckedSource[String,SubscriptionRef]
,queueName:String
,splitLength:Int)(隐式actorSystem:actorSystem):图形[ClosedShape,Future[Done]={
GraphDSL.create(Sink.ignore){隐式生成器:GraphDSL.builder[Future[Done]]=>s=>
val toShort=0
瓦尔·托隆=1
//交叉点
val split=builder.add(分区[AckTup[String]](2,(tup:AckTup[String])=>{
val(p,s)=tup
如果(s.lengthAckedFlow(before).wrappedRepr
拆分前~>拆分
//必须先做短的,然后再做长的,因为分割的顺序是这样的
split~>AckedFlow(短).wrappedRepr~>merge
split~>AckedFlow(long).wrappedRepr~>merge
//在最后一个AckedFlow之后,请确保“.acked”,以便将消息从队列中删除
合并~>AckedFlow(之后).acked~>s
封闭形状
}}
正如Stefano Bonetti所说,关键是使用与
AckedFlow
关联的.wrappedRepr
,然后使用.acked
组合器作为最后一步。这是我似乎无法使用的代码:`def buildModelAcked(来源:AckedSource[String,SubscriptionRef],queueName:String)(隐式actorSystem:actorSystem):图形[ClosedShape,Future[Done]={GraphDSL.create(Sink.ignore){隐式生成器:GraphDSL.builder[Future[Done]=>s=>///source.map(Message.queue(,queueName))~>AckedFlow(toStringFlow)~>AckedSink.ack source(Message.queue(,queueName))。通过(AckedFlow(toStringFlow))。到(AckedSink.ack)ClosedShape}在没有dsl的情况下工作,但无法解析~>运算符。你能给我一个简单的例子吗?谢谢Cellent!这是缺少的一部分。谢谢,特别是为了得到~>
和其他奇特的运算符,你需要在dsl构建函数体中导入GraphDSL.Implicits.\u
。谢谢,我已经更新了代码以获得导入,但它仍然无法解析`~>`运算符