在Slick事务中处理Akka流
软件版本:在Slick事务中处理Akka流,akka,slick,akka-stream,slick-3.0,Akka,Slick,Akka Stream,Slick 3.0,软件版本: Akka 2.4.4 滑头3.1.0 我想在光滑的事务中处理来自Akka流的元素。 下面是一些简化的代码来说明一种可能的方法: def insert(d: AnimalFields): DBIO[Long] = animals returning animals.map(_.id) += d val source: Source[AnimalFields, _] val sourceAsTraversable = ??? db.run((for { ids <-
- Akka 2.4.4
- 滑头3.1.0
def insert(d: AnimalFields): DBIO[Long] =
animals returning animals.map(_.id) += d
val source: Source[AnimalFields, _]
val sourceAsTraversable = ???
db.run((for {
ids <- DBIO.sequence(sourceAsTraversable.map(insert))
} yield { ids }).transactionally)
现在我可以将可遍历队列传递给DBIO.sequence()
。但是,这违背了流式处理的目的
我发现的另一种方法是:
def toDbioAction[T](queue: SinkQueue[DBIOAction[S, NoStream, Effect.All]]):
DBIOAction[Queue[T], NoStream, Effect.All] =
DBIO.from(queue.pull() map { tOption =>
tOption match {
case Some(action) =>
action.flatMap(t => toDbioAction(queue).map(_ :+ t))
case None => DBIO.successful(Queue())
}
}).flatMap(r => r)
使用此方法,可以在不阻塞的情况下生成DBIOActions序列:
toDbioAction(source.runWith(Sink.queue()))
有没有更好/更惯用的方法来达到预期的效果?以下是我对
sourceAsTraversable
的实现:
import scala.collection.JavaConverters._
def sourceAsTraversable[A](source: Source[A, _])(implicit mat: Materializer): Traversable[A] =
source.runWith(StreamConverters.asJavaStream()).iterator().asScala.toIterable
TraversableQueue
的问题是forEach
必须完全处理流-它不支持“break”概念,因此像“drop”/“take”等方法仍然必须处理整个源代码。从错误处理和快速失败的角度来看,这可能很重要。我认为这是一个很好的解决方案。您需要在最后阻塞,以便在单个事务中运行;而且,在调用db.run()
之前,Slick实际上不会向数据库发送任何内容。
import scala.collection.JavaConverters._
def sourceAsTraversable[A](source: Source[A, _])(implicit mat: Materializer): Traversable[A] =
source.runWith(StreamConverters.asJavaStream()).iterator().asScala.toIterable