akka数据流和副作用

时间:2013-05-26 22:04:29

标签: scala akka continuations dataflow

我正在使用akka数据流,我想知道是否有办法让特定的代码块等待未来的完成,而不会明确地使用未来的值。

实际的用例是我有一个文件,我希望在特定的未来完成时删除该文件,但不是之前。这是一个粗略的例子。首先想象我有这项服务:

trait ASync {
   def pull: Future[File]
   def process(input : File): Future[File]
   def push(input : File): Future[URI]
}

我有一个工作流程,我想以非阻塞的方式运行:

val uriFuture = flow {
    val pulledFile = async.pull(uri)
    val processedile = async.process(pulledFile())
    val storedUri = async.push(processedFile())

    // I'd like the following line executed only after storedUri is completed, 
    // not as soon as pulled file is ready.
    pulledFile().delete()

    storedUri()
}

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

val uriFuture = flow {
  val pulledFile = async.pull(uri)
  val processedile = async.process(pulledFile())
  val storedUri = for(uri <- async.push(processedFile())) yield {
    pulledFile().delete()
    uri
  }
  storedUri()
}

在此示例中,只有来自pulledFile.delete的{​​{1}}成功,才会调用Future。如果失败,则不会调用pushdelete未来的结果仍然是调用storedUri的结果。

或者另一种方式是:

push

这里的不同之处在于,无论val uriFuture = flow { val pulledFile = async.pull(uri) val processedile = async.process(pulledFile()) val storedUri = async.push(processedFile()) andThen{ case whatever => pulledFile().delete() } storedUri() } 成功还是失败,都会调用deletepush的结果仍然是调用storedUri的结果。

答案 1 :(得分:0)

您可以将回调用于非阻止工作流程:

future onSuccess {
  case _ => file.delete() //Deal with cases obviously... 

}

来源:http://doc.akka.io/docs/akka/snapshot/scala/futures.html

或者,您可以使用Await.result阻止:

val result = Await.result(future, timeout.duration).asInstanceOf[String]

后者通常在你需要阻止时使用 - 例如在测试用例中 - 而非阻塞性能更高,因为你没有停止一个线程来启动另一个线程只是为了再次恢复另一个线程 - 这比一个慢异步活动,因为资源管理开销。

类型安全的工作人员称其为“反应性”。这有点像流行语。如果你在工作场所使用它,我会笑。