Playframework 在akka stream中使用源代码两次
我正在为我构建的web应用程序使用Play框架。Play 2.5使用Akka Stream API来允许请求/响应流 我有一个端点,传入的文件直接流式传输到Google Drive 我定义了一个如下所示的Playframework 在akka stream中使用源代码两次,playframework,streaming,akka-stream,Playframework,Streaming,Akka Stream,我正在为我构建的web应用程序使用Play框架。Play 2.5使用Akka Stream API来允许请求/响应流 我有一个端点,传入的文件直接流式传输到Google Drive 我定义了一个如下所示的BodyParser: BodyParser("toDrive") { request => Accumulator.source[ByteString].mapFuture { source => Future.successful(Right("Done")) }
BodyParser
:
BodyParser("toDrive") { request =>
Accumulator.source[ByteString].mapFuture { source =>
Future.successful(Right("Done"))
}
}
我使用源代码(source[ByteString,]
)并将其馈送到我与Play提供的WSClient
一起使用的StreamedBody
我想使用给定的源代码
,并使用WSClient
进行两个不同的HTTP调用
我尝试了这种天真的方法,将相同的源代码
传递到两个不同的WSClient
调用中,但失败了。我认为解决我问题的办法是广播
我想从源代码中得到什么来创建两个源代码,供我的WSClient
使用
我还在玩Source
、Flow
和Sink
。我正试图弄明白这一切。我想.alsoTo()
源代码的方法就是你想要的。内部只是广播。更新的解决方案:
Accumulator[ByteString, Either[Result, String]] {
val s1 = Sink
.asPublisher[ByteString](fanout = false)
.mapMaterializedValue(Source.fromPublisher)
.mapMaterializedValue { source =>
//do what you need with source
Future.successful(Right("result 1"))
}
val s2 = Sink
.asPublisher[ByteString](fanout = false)
.mapMaterializedValue(Source.fromPublisher)
.mapMaterializedValue { source =>
//do what you need with source
Future.successful(Right("result 2"))
}
def combine(val1: Future[Either[Result, String]],
val2: Future[Either[Result, String]]): Future[Either[Result, String]] = {
for {
res1 <- val1
res2 <- val2
} yield {
// do something with your result
res1.right.flatMap(val1 => res2.right.map(val2 => val1 + val2))
}
}
Sink.fromGraph(GraphDSL.create(s1, s2)(combine) { implicit b => (sink, sink2) =>
import GraphDSL.Implicits._
val broadcast = b.add(Broadcast[ByteString](2))
broadcast ~> sink
broadcast ~> sink2
SinkShape(broadcast.in)
})
}
与我最初的方法相比,唯一有效的改变是我自己创建了Sink
并允许fanout
,这样我可以在两个不同的WSClient
调用中使用源代码两次
你觉得专家怎么样
BodyParser("toDrive") { request =>
def sourceToFut(src: Source): Future[T] = ???
Accumulator[ByteString, Either[Result, T]] {
Sink
.asPublisher[ByteString](fanout = true)
.mapMaterializedValue(Source.fromPublisher)
.mapMaterializedValue { source =>
val upload1Fut = sourceToFut(source)
val upload2Fut = sourceToFut(source)
for {
file1 <- upload1Fut
file2 <- upload2Fut
} yield {
(file1, file2)
}
}
}
}