scala Play - 重复的WS调用 - 使其成为异步

时间:2015-06-10 17:36:50

标签: web-services scala asynchronous playframework

在Play框架的控制器中,我正在调用外部Web服务,在那里上传文件。上传文件后,外部服务器将处理它,我将需要取回已处理的文件。

由于处理可能需要很长时间,因此我每隔几秒钟就会进行一次http调用以查看该文件是否存在。一旦我恢复了OK状态,我再次调用以检索已处理的文件。

问题是我必须每隔几秒重复拨打同一个电话,并且只有在我获得OK状态后才能继续。目前我使用 Await 让它工作 - 我一直在等待并再次打电话,直到我获得OK状态。

当然,这是阻挡,在Play中它是一个很大的禁忌。

什么方法可以使这种异步?

以下是我目前的代码

<code>
 //keep checking until converted file exists, then download                
 futureResponse = fileURLFut.flatMap {
                      convertedFileURL =>                                         
                        //keep checking response status until OK (200)or until too much time passes                                      
                        var counter = 0
                        var respStatus: Int = 0
                        do {                          
                           if (counter == 30) {
                            //waited too long - interrupt the loop
                            throw new RuntimeException("Converted file not found.")
                           }   
                           //TODO this will have to be done without blocking
                           Thread.sleep(2000)
                           counter = counter + 1                      
                           respStatus = Await.result(       WS.url(convertedFileURL).withAuth(user.get, password.get, AuthScheme.BASIC)
                                   .get.map(_.status),  duration.Duration(10000, "millis"))
                           Logger.debug("Checking if file exists...  " + counter + " status = " + respStatus)                                                   
                        } while (respStatus != 200)

                        Logger.debug("File exists. Will download now.")

                        var sss= WS.url(convertedFileURL)
                          .withAuth(user, password, AuthScheme.BASIC)
                          .get
</code>

1 个答案:

答案 0 :(得分:1)

尝试这样的事情:

def runRequest(...): Future[Result] = 
  WS.url(convertedFileURL).withAuth(user.get, password.get, AuthScheme.BASIC)

def tryOnce(triesLeft: Int): Future[Result] =
  if (triesLeft == 0) Future.failed(throw new RuntimeException("Converted file not found."))
  else runRequest(...) flatMap { res =>
    if (res.status == 200) Future.successful(res)
    else
      akka.pattern.after(2 seconds, using = system.scheduler)(tryOnce(triesLeft - 1))
  }

tryOnce(triesLeft = 30)