我想通过scalaz-stream通过db.stream(你的查询)流式传输从一个灵活的3.0.0查询返回的数据。
看起来,reactive-streams.org使用的是不同库实现的API和数据流模型。
如何通过从scalaz-stream流程回流到光滑的出版商的背压来做到这一点?
答案 0 :(得分:3)
查看https://github.com/krasserm/streamz
Streamz是scalaz-stream的资源组合器库。它允许Process实例使用和生成:
答案 1 :(得分:2)
我终于回答了我自己的问题。如果您愿意使用scalaz-streams队列来排队流式传输结果。
def getData[T](publisher: slick.backend.DatabasePublisher[T],
queue: scalaz.stream.async.mutable.Queue[T], batchRequest: Int = 1): Task[scala.concurrent.Future[Long]] =
Task {
val p = scala.concurrent.Promise[Unit]()
var counter: Long = 0
val s = new org.reactivestreams.Subscriber[T] {
var sub: Subscription = _
def onSubscribe(s: Subscription): Unit = {
sub = s
sub.request(batchRequest)
}
def onComplete(): Unit = {
sub.cancel()
p.success(counter)
}
def onError(t: Throwable): Unit = p.failure(t)
def onNext(e: T): Unit = {
counter += 1
queue.enqueueOne(e).run
sub.request(batchRequest)
}
}
publisher.subscribe(s)
p.future
}
当您使用run
运行此操作时,您将获得一个完成后的未来,意味着查询已完成流式传输。如果您希望计算等待所有数据到达,您可以撰写此未来。您还可以在getData
中的任务中添加使用Await,然后如果您需要在继续之前运行所有数据,则在返回的Task对象上组合您的计算。对于我所做的事情,我将在未来完成并关闭队列,以便我的scalaz-stream知道干净地终止。
答案 2 :(得分:0)
这是一个稍微不同的实现(比用户1763729发布的实现)返回一个进程:
def getData[T](publisher: DatabasePublisher[T], batchSize: Long = 1L): Process[Task, T] = {
val q = async.boundedQueue[T](10)
val subscribe = Task.delay {
publisher.subscribe(new Subscriber[T] {
@volatile var subscription: Subscription = _
override def onSubscribe(s: Subscription) {
subscription = s
subscription.request(batchSize)
}
override def onNext(next: T) = {
q.enqueueOne(next).attemptRun
subscription.request(batchSize)
}
override def onError(t: Throwable) = q.fail(t).attemptRun
override def onComplete() = q.close.attemptRun
})
}
Process.eval(subscribe).flatMap(_ => q.dequeue)
}