Slick 如何将scalaz流连接到反应流(如reactive streams.org)

Slick 如何将scalaz流连接到反应流(如reactive streams.org),slick,scalaz-stream,Slick,Scalaz Stream,我想通过db.stream(yourquery)通过scalaz stream来流式传输从光滑的3.0.0查询返回的数据 看起来reactive-streams.org被用于不同库实现的API和数据流模型 当背压从scalaz stream流程流回光滑的出版商时,你是如何做到这一点的?我终于回答了自己的问题。如果您愿意使用scalaz streams队列对流结果进行排队 def getData[T](publisher: slick.backend.DatabasePublisher[T],

我想通过db.stream(yourquery)通过scalaz stream来流式传输从光滑的3.0.0查询返回的数据

看起来reactive-streams.org被用于不同库实现的API和数据流模型


当背压从scalaz stream流程流回光滑的出版商时,你是如何做到这一点的?

我终于回答了自己的问题。如果您愿意使用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
中的任务中添加使用等待,然后在返回的任务对象上组合计算。对于我要做的事情,我在将来完成时编写并关闭队列,以便我的scalaz流知道如何干净地终止。

看一看

Streamz是scalaz stream的资源组合器库。它允许流程实例从以下内容消费和生产:

  • ApacheCamel端点
  • Akka持久性日志和快照存储以及
  • Akka流(反应流)具有全背压支撑

这里有一个稍微不同的实现(与user1763729发布的实现不同),它返回一个进程:

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

您可以将问题概括为:如何将scalaz流连接到反应流(如reactive streams.org)