Akka Streams scala DSL和Op Rabbit

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 --> | | --&

我已经开始使用Akka Streams和Op Rabbit,我有点困惑

我需要基于谓词分割流,然后将它们组合起来,就像我在创建图和使用分区和合并时所做的那样

我已经能够使用GraphDSL.Builder做类似的事情,但似乎无法让它与AckedSource/Flow/Sink一起工作

该图如下所示:

                        | --> 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)
}
}}

编译器无法解析
~>
运算符

因此,我的问题是:

  • 是否有一个使用scala dsl构建Acked/Source/Flow/Sink图形的示例项目

  • 是否有一个划分和合并的示例项目与我在这里尝试的类似


  • 在处理问题时,请记住以下定义

  • 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的
    承诺[单元]
  • GraphDSL边缘操作符(
    ~>
    )将适用于一组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
    。谢谢,我已经更新了代码以获得导入,但它仍然无法解析`~>`运算符