在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>
答案 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)