Akka Streams: состояние в потоке

Я хочу прочитать несколько больших файлов, используя потоки Akka для обработки каждой строки. Представьте, что каждый ключ состоит из (identifier -> value). Если новый идентификатор найден, я хочу сохранить его и его значение в базе данных; в противном случае, если идентификатор уже найден при обработке потока строк, я хочу сохранить только значение. Для этого я думаю, что мне нужен какой-то рекурсивный поток состояний, чтобы сохранить идентификаторы, которые уже были найдены в Map. Я думаю, что получу в этом потоке пара (newLine, contextWithIdentifiers).

Я только начал смотреть на потоки Akka. Я думаю, я могу управлять собой, чтобы сделать процессинг без гражданства, но я понятия не имею, как сохранить contextWithIdentifiers. Я бы признателен за любые указатели в правильном направлении.

1 ответов


может быть, что-то вроде statefulMapConcat могу помочь вам:

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}
import scala.util.Random._
import scala.math.abs
import scala.concurrent.ExecutionContext.Implicits.global

implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()

//encapsulating your input
case class IdentValue(id: Int, value: String)
//some random generated input
val identValues = List.fill(20)(IdentValue(abs(nextInt()) % 5, "valueHere"))

val stateFlow = Flow[IdentValue].statefulMapConcat{ () =>
  //state with already processed ids
  var ids = Set.empty[Int]
  identValue => if (ids.contains(identValue.id)) {
    //save value to DB
    println(identValue.value)
    List(identValue)
  } else {
    //save both to database
    println(identValue)
    ids = ids + identValue.id
    List(identValue)
  }
}

Source(identValues)
  .via(stateFlow)
  .runWith(Sink.seq)
  .onSuccess { case identValue => println(identValue) }