2015-03-28 4 views
6

В маршрутизации akka-http я могу вернуть Future в качестве ответа, который неявно преобразуется в ToResponseMarshaller.Как отрегулировать время отклика?

Есть ли способ справиться с таймаутом этого будущего? Или таймаут соединения на уровне маршрута? Или один способ использовать функцию Await()?

Прямо сейчас клиент может ждать ответа навсегда.

complete { 
    val future = for { 
    response <- someIOFunc() 
    entity <- someOtherFunc() 
    } yield entity 
    future.onComplete({ 
    case Success(result) => 
     HttpResponse(entity = HttpEntity(MediaTypes.`text/xml`, result)) 
    case Failure(result) => 
     HttpResponse(entity = utils.getFault("fault")) 
    }) 
    future 
} 
+0

Пожалуйста, объясните, где требуется тайм-аут в вашем коде? Ваш код кажется неправильным: вы создаете HttpResponse в onSuccess и не устанавливаете его везде и не возвращаете. Если вы хотите преобразовать результат в будущую модель метода использования –

+0

Мне нужно отправить ответ с сообщением о неисправности, если someIOFunc() выполняется в течение длительного времени (например, 1 минута). Возможно, шаблон с «onSuccess» неверен, но этот код возвращает правильный ответ, когда успех. Это меня смущает, но я не могу понять, как работает преобразование из будущего в ответ. В источниках есть глубокие слои абстракции, и я не могу понять эту часть. – diemust

+0

Просто удалите 'future' в конце блока. Фьючерсы, как и другие конструкции Scala, являются неизменяемыми структурами данных, которые вызывают методы на них, возвращают еще один фьючерс. Когда вы вызываете метод onComplete, он возвращает новое будущее с помощью 'HttpResponse'. –

ответ

13

Добавление тайм-аут, чтобы асинхронной операции означает создание нового будущего, который завершается либо самой операции, или тайм-аут:

import akka.pattern.after 
val future = ... 
val futureWithTimeout = Future.firstCompletedOf(
    future :: 
    after(1.second, system.scheduler)(Future.failed(new TimeoutException)) :: 
    Nil 
) 

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

В качестве побочного примечания: представленный образец кода содержит мертвый код, регистрация обработчика onComplete в будущем имеет смысл только для побочных эффектов, но вы, похоже, хотите изменить значение будущего и создать из него HttpEntity. Это должно быть сделано с помощью map и recover:

future 
    .map(result => HttpResponse(entity = HttpEntity(MediaTypes.`text/xml`, result))) 
    .recover { case ex => HttpResponse(entity = utils.getFault("fault")) } 

Это будет затем общее возвращаемое значение, которое передается в complete директивы.

+0

Немного о теме, но я видел, что это предпочтительный образец использования тайм-аутов в Акке. Но что происходит с другим будущим, когда происходит таймаут? Он будет работать до тех пор, пока не будет завершен, и занять поток в исполнителе до его завершения, независимо от того, как долго? – NilsH

+3

Да, это по дизайну: проведение «Будущего» означает, что у вас есть доступ только для чтения к предоставленному значению, а возможность отмены - это нечто, что подразумевает более исключительное право. Аннулирование само по себе невозможно на JVM, но если вы держите «Promise» вместо этого, вы можете его завершить, и код, который вычисляет реальное значение, может прерваться, когда он увидит это - это руководство, потому что принудительная аннулирование невозможна. –

+0

Это имеет смысл. Но это также означает, что Будущее, которое «зависает», не будет выпускать его ресурсы до тех пор, пока оно не завершится (или не сработает на каком-то другом уровне), независимо от продолжительности. Каково надлежащее действие, чтобы избежать голода в потоке в сценарии async, подобном этому? – NilsH

Смежные вопросы