0

I'm using answer from this thread because I need to treat first element especially. The problem is, I need to send this data to another Actor or persist locally (which is not possibl).

So, my stream looks like this:

val flow: Flow[Message, Message, (Future[Done], Promise[Option[Message]])] = Flow.fromSinkAndSourceMat(
  Flow[Message].mapAsync[Trade](1) {
    case TextMessage.Strict(text) =>
      Unmarshal(text).to[Trade]
    case streamed: TextMessage.Streamed =>
      streamed.textStream.runFold("")(_ ++ _).flatMap(Unmarshal(_).to[Trade])
  }.groupBy(pairs.size, _.s).prefixAndTail(1).flatMapConcat {
    case (head, tail) =>
      // sending first element here
      val result = Source(head).to(Sink.actorRefWithAck(
        ref = actor,
        onInitMessage = Init,
        ackMessage = Ack,
        onCompleteMessage = "done"
      )).run()
      // some kind of operation on the result
    Source(head).concat(tail)
  }.mergeSubstreams.toMat(sink)(Keep.right),
  Source.maybe[Message])(Keep.both)

Is this a good practice? Will it have unintended consequences? Unfortunately, I cannot call persist inside stream, so I want to send this data to the external system.

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
artyomboyko
  • 2,781
  • 5
  • 40
  • 54
  • Your comment tells me you plan on doing additional operations on the result, and probably blocking on it. Instead, why not do an ask (?) and put the future in the tuple that travels down the stream. The ask and the post processing can be performed in a for comprehension. The elements in "rest" can be wrapped in a FastFuture to make the types consistent. – Grant BlahaErath Jun 18 '18 at 18:03

1 Answers1

1

Your current approach doesn't use result in any way, so a simpler alternative would be to fire and forget the first Message to the actor:

groupBy(pairs.size, _.s).prefixAndTail(1).flatMapConcat {
  case (head, tail) =>
    // sending first element here
    actor ! head.head

    Source(head).concat(tail)
}

The actor would then not have to worry about handling Init and sending Ack messages and could be solely concerned with persisting Message instances.

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
  • the problem is that I will use result. Sorry for the confusion. The data is very important in this case, so I need to use `actorRefWithAck` or `persist`. That's the problem. I cannot just fire and forget in this case. – artyomboyko Jun 17 '18 at 13:44