Полный ответ akka-http с итератором - PullRequest
0 голосов
/ 13 июня 2018

У меня есть итератор результатов запроса mongodb, и я хочу передать эти результаты в ответ http без загрузки всего набора результатов в память.

Возможно ли заполнить ответ akka http итератором вместоколлекция или будущее?

Ответы [ 2 ]

0 голосов
/ 15 июня 2018

Учитывая Iterator данных:

type Data = ???

val dataIterator : () => Iterator[Data] = ???

Сначала вам понадобится функция для преобразования представления Data в ByteString и ContentType (, например, json, binary, csv, xml, ... ) представления:

import akka.util.ByteString
import akka.http.scaladsl.model.ContentType    

val dataToByteStr : Data => ByteString = ???

//see akka.http.scaladsl.model.ContentTypes for possible values
val contentType : ContentType = ???

Теперь функцию итератора и конвертера можно использовать для создания HttpResponse, который будет передавать результаты обратно клиенту http без удержаниявесь набор данных в памяти:

import akka.http.scaladsl.model.HttpEntity.{Chunked, ChunkStreamPart}
import akka.http.scaladsl.model.ResponseEntity    
import akka.stream.scaladsl.Source
import akka.http.scaladsl.model.HttpResponse

val chunks : Source[ChunkStreamPart,_] = 
  Source.fromIterator(dataIterator)
        .map(dataToByteStr)
        .map(ChunkStreamPart.apply)

val entity : ResponseEntity = Chunked.fromData(contentType, chunks)

val httpResponse : HttpResponse = HttpResponse(entity=entity)

Примечание. Поскольку каждый раз из dataIterator создается новый итератор, вам не нужно создавать новый httpResponse для каждого входящего запроса;один и тот же ответ может быть использован для всех запросов.

0 голосов
/ 13 июня 2018

Посмотрите на разъем Alpakka MongoDB .Он позволяет создать один источник из коллекции Mongo, например:

val source: Source[Document, NotUsed] = MongoSource(numbersColl.find())

val rows: Future[Seq[Document]] = source.runWith(Sink.seq)

Или, возможно, вы захотите создать собственную реализацию исходного кода, например, GraphStage.

...