Преобразовать источник [ByteString, Any] в источник [ByteString, IOResult] - PullRequest
0 голосов
/ 30 августа 2018

У меня есть:

val fileStream: Source[ByteString, Any] = Source.single(ByteString.fromString("Hello"))

Этот тип Source[ByteString, Any] происходит из директивы akka fileUpload:

https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/file-upload-directives/fileUpload.html

Могу ли я преобразовать это в Source[ByteString, IOResult] или, в качестве альтернативы, выполнить какую-то другую операцию, аналогичную Source.single(ByteString.fromString("Hello")), которая вернула бы мне Source[ByteString, IOResult] из строки?

Я могу создать результат ввода-вывода с помощью:

val ioResult: IOResult = IOResult.createSuccessful(1L)

и ByteString с:

val byteString: ByteString = ByteString.fromString("Hello")

так что теперь мне просто нужны они как Source[ByteString, IOResult]

Обратите внимание, это только для модульного теста, я тестирую функцию, которая возвращает Source[ByteString, IOResult], и поэтому я хотел бы создать экземпляр этого (без необходимости создания файла) для утверждения функции возвращает правильный ByteString, меня не волнует IOResult часть Source.

1 Ответ

0 голосов
/ 30 августа 2018

Специально для директивы загрузки файлов

Я подозреваю, что авторы fileUpload сохранили тип материализации как Any, чтобы учесть будущие изменения в API. Оставив это значение Any, они могут позже изменить его на тип, на котором они действительно хотят остановиться.

Таким образом, даже если вы можете привести к IOResult, вы можете столкнуться с проблемами в будущем, если вы обновите версию akka и тип изменился ...

Материализация в целом

Второй тип в параметрах типа Source указывает, во что «материализуется» поток. Используя ваш пример кода и изменив Any на фактический тип NotUsed, мы можем показать весь жизненный цикл потока:

val notUsed : NotUsed = Source.single(ByteString.fromString("Hello"))
                              .toMat(Sink.ignore)(Keep.left)
                              .run()

Как вы можете видеть, когда поток запускается, он превращается в фактическое значение (то есть материализованное). В приведенном выше случае тип значения - NotUsed. Это потому, что вы мало что можете сделать с потоком, который получает одно значение.

Сравните этот поток с потоком, который работает с файлом :

val file = Paths.get("example.csv")

val fileIOResult: Future[IOResult] = FileIO.fromPath(file)
                                           .to(Sink.ignore)
                                           .run()

В этом случае поток читает содержимое файла и передает его на Sink. Здесь было бы полезно узнать, были ли какие-либо ошибки при чтении файла. Чтобы узнать, насколько хорошо прошло чтение файла, поток материализован в Future[IOResult], который можно использовать для получения информации о чтении файла:

fileIOResult foreach { ioResult =>
  println(s"read ${ioResult.count} bytes from file")
}

Следовательно, не имеет смысла "конвертировать" Any в IOResult ...

...