2013-12-23 3 views
4

Я реализую API доставки файлов AWS S3. Я вынужден передать байты из S3SbjectInputStream в браузер. У нас есть прецедент, обслуживающий файл с облачным экраном, не является вариантом (в основном локальная разработка)Play Framework [2.2-scala]: создание перечислителя из медленного InputStream

У меня есть InputStream, поэтому наиболее очевидной задачей было бы использовать Ok.chunked с Enumerator.fromStream (), но Enumerator.fromStream() имеет очень четкое предупреждение о том, что поток не должен быть медленным. Я предполагаю, что AWS S3ObjectInputStream, вероятно, является одним из самых медленных потоков.

http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.libs.iteratee.Enumerator$

def fromStream(input: InputStream, chunkSize: Int = 1024 * 8) 
       (implicit ec: ExecutionContext): Enumerator[Array[Byte]] 

Create an enumerator from the given input stream. 

This enumerator will block on reading the input stream, in the default iteratee 
thread pool. Care must therefore be taken to ensure that this isn't a 
slow stream. If using this with slow input streams, consider setting the value 
of iteratee-threadpool-size to a value appropriate for handling the blocking. 

Так мне было интересно, что самый безопасный способ, чтобы избежать зависанию и получить файл потокового в браузере, не держа весь файл в память.

Есть ли другой способ получить Enumerator (или что-то, что мы можем отправить в результате) из InputStream?

+0

Другой случай использования будет пользовательские разрешения на объекты в S3, то вам нужно по-прежнему передавать байты ... – Jaap

+0

Возможно, вы можете использовать unoldM? –

+0

Вы нашли решение? – nachokk

ответ

1

Я действительно как-то неправильно понял документацию. Enumerator.fromStream имеет неявный ExecutionContext, который вы можете предоставить.
Если вы создаете выделенный контекст для этого конкретного типа операций, вы все равно можете испытать головоломку потока, но вы контролируете, в какой threadpool попадает эта проблема.

Мы используем игру! так что мы можем просто настроить AKKA threadpools в нашем application.conf:

# this is a root value in the application.conf, but you can put it anywhere 
# as long as you provide the full path to the .lookup() function 
my-contexts { 
    s3-streaming { 
    fork-join-executor { 
     parallelism-min = 50 
     parallelism-max = 50 
    } 
    } 
} 

и использовать их в коде, как это:

object MyContexts { 
    val s3Streaming: ExecutionContext = 
    Akka.system.dispatchers.lookup("my-contexts.s3-streaming") 
} 

... 

Enumerator.fromStream(stream)(MyContexts.s3Streaming)