我有以下图表。
在inflateFlow
阶段,我检查是否已在DB中处理了请求。如果已经处理完消息,我想返回MsgSuccess
而不是RequestProcess
,但下一个FlowShape
将不接受,它需要RequestProcess
。有没有办法从flowInflate
跳到flowWrap
而无需在任何地方添加Either
?
GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
import GraphDSL.Implicits._
val flowInflate = builder.add(wrapFunctionInFlowShape[MsgRequest, RequestProcess](inflateFlow))
val flowProcess = builder.add(wrapFunctionInFlowShape[RequestProcess, SuccessProcess](convertFlow))
val flowWrite = builder.add(wrapFunctionInFlowShape[SuccessProcess, SuccessProcess](writeFlow))
val flowWrap = builder.add(wrapFunctionInFlowShape[SuccessProcess, MsgSuccess](wrapFlow))
flowInflate ~> flowProcess ~> flowWrite ~> flowWrap
FlowShape(flowInflate.in, flowWrap.out)
}
def wrapFunctionInFlowShape[Input, Output](f: Input => Output): Flow[Input, Output, NotUsed] = {
Flow.fromFunction { input =>
f(input)
}
}
//check for cache
def inflateFlow(msgRequest: MsgRequest): Either[RequestProcess, MsgSuccess] = {
val hash: String = hashMethod(msgRequest)
if(existisInDataBase(hash))
Right(MsgSuccess(hash))
else
Left(inflate(msgRequest))
}
def convertFlow(requestPorocess: RequestPocess): SuccessProcess = {}//process the request}
def writeFlow(successProcess: SuccessProcess): SuccessProcess = {}//write to DB}
def wrapFlow(successProcess: SuccessProcess): MsgSuccess = {}//wrap and return the message}
答案 0 :(得分:1)
您可以使用分区在流中定义备用路径。在您的情况下,PartitionWith
项目中的Akka Stream Contrib阶段可能会有所帮助。与标准Akka Streams API中的Partition
阶段不同,PartitionWith
允许输出类型不同:在您的情况下,输出类型为RequestProcess
和MsgSuccess
。
首先,要使用PartitionWith
,请将以下依赖项添加到build.sbt
:
libraryDependencies += "com.typesafe.akka" %% "akka-stream-contrib" % "0.8"
其次,用分区替换inflateFlow
:
def split = PartitionWith[MsgRequest, RequestProcess, MsgSuccess] { msgRequest =>
val hash = hashMethod(msgRequest)
if (!existisInDataBase(hash))
Left(inflate(msgRequest))
else
Right(MsgSuccess(hash))
}
然后将该阶段合并到您的图表中:
val flow = Flow.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
import GraphDSL.Implicits._
val pw = builder.add(split)
val flowProcess = builder.add(wrapFunctionInFlowShape[RequestProcess, SuccessProcess](convertFlow))
val flowWrite = builder.add(wrapFunctionInFlowShape[SuccessProcess, SuccessProcess](writeFlow))
val flowWrap = builder.add(wrapFunctionInFlowShape[SuccessProcess, MsgSuccess](wrapFlow))
val mrg = builder.add(Merge[MsgSuccess](2))
pw.out0 ~> flowProcess ~> flowWrite ~> flowWrap ~> mrg.in(0)
pw.out1 ~> mrg.in(1)
FlowShape(pw.in, mrg.out)
})
如果在数据库中找不到传入的MsgRequest
并将其转换为RequestProcess
,则该消息将通过您的原始流路径。如果传入的MsgRequest
在数据库中并解析为MsgSuccess
,则它会绕过流中的中间步骤。在这两种情况下,生成的MsgSuccess
消息都会从两个备用路径合并到一个流出口。