Scala 从PushPullStage发射多个对象

Scala 从PushPullStage发射多个对象,scala,akka,akka-stream,Scala,Akka,Akka Stream,我一直在玩Akka Streams,我试图通过实现自己的PushPullStage来定制流。我希望流将它从上游接收到的对象累积到一个列表中,并根据某个函数对它们进行分组,然后在上游完成时向下游发送分组 这似乎是一件很容易实现的事情,但我不知道怎么做!似乎没有办法从PushPullStage发射多个对象 以下是我迄今为止的实施情况: class Accumulate[A] extends PushPullStage[A, List[A]] { private var groups: Lis

我一直在玩Akka Streams,我试图通过实现自己的
PushPullStage
来定制
流。我希望
将它从上游接收到的对象累积到一个列表中,并根据某个函数对它们进行分组,然后在上游完成时向下游发送分组

这似乎是一件很容易实现的事情,但我不知道怎么做!似乎没有办法从
PushPullStage
发射多个对象

以下是我迄今为止的实施情况:

class Accumulate[A] extends PushPullStage[A, List[A]] {
    private var groups: List[List[A]] = Nil

    private def group(x: A): List[List[A]] = ...

    override def onPush(elem: A, ctx: Context[A]): SyncDirective = {
      groups = group(elem)
      ctx.pull()
    }

    override def onPull(ctx: Context[A]): SyncDirective =
      if (ctx.isFinishing) {
        for(group <- groups)
          ctx.push(group)    // this doesn't work

        ctx.finish()
      } else {
        ctx.pull()
      }

    override def onUpstreamFinish(ctx: Context[A]): TerminationDirective =
      ctx.absorbTermination()
  }
}

你不能推得比要求的更多,因为那样会违反背压。 另外,值得注意的是,我不推荐您尝试执行的操作,因为对于大型或无界流,这将导致OutOfMemory错误

class Accumulate[A] extends PushPullStage[A, List[A]] {
    private var groups: List[List[A]] = Nil

    private def group(x: A): List[List[A]] = ...

    override def onPush(elem: A, ctx: Context[A]): SyncDirective = {
      groups = group(elem)
      ctx.pull()
    }

    override def onPull(ctx: Context[A]): SyncDirective =
      if (ctx.isFinishing) {
        groups match {
          case Nil => ctx.finish()
          case group :: rest =>
            groups = rest
            ctx.push(group)
        }
      } else {
        ctx.pull()
      }

    override def onUpstreamFinish(ctx: Context[A]): TerminationDirective =
      ctx.absorbTermination()
  }
}

啊,我没想到背压。我稍微修改了代码,现在它按预期工作(请参阅我的编辑)。谢谢:)
class Accumulate[A] extends PushPullStage[A, List[A]] {
    private var groups: List[List[A]] = Nil

    private def group(x: A): List[List[A]] = ...

    override def onPush(elem: A, ctx: Context[A]): SyncDirective = {
      groups = group(elem)
      ctx.pull()
    }

    override def onPull(ctx: Context[A]): SyncDirective =
      if (ctx.isFinishing) {
        groups match {
          case Nil => ctx.finish()
          case group :: rest =>
            groups = rest
            ctx.push(group)
        }
      } else {
        ctx.pull()
      }

    override def onUpstreamFinish(ctx: Context[A]): TerminationDirective =
      ctx.absorbTermination()
  }
}