我试图弄清楚如何以递归方式使用Scala Futures。我的用例是将资源(ResourceOne)的输出与另一个资源(ResourceTwo)输出进行比较,如果在我想要同步第一个资源(ResourceOne)并再次检索资源的过程中它们之间存在任何差异。我从resourceOne检索的项目数与resourceTwo同步。但是由于我的操作(检索和删除)与ResourceOne返回Future,我陷入了逻辑的一半。下面是一个说明我的问题的示例,对于完成步骤#3和#4以及在步骤#5中递归#1到#4的任何想法?
package com.example
import scala.concurrent.Future
import scala.collection.mutable.Map
import scala.concurrent.ExecutionContext.Implicits.global
object ResourceOne {
//var resources = List("one", "two","three","four","five","six","seven","eight","nine")
var resources = List("one", "two","three")
def getFirstFive():Future[List[String]] = Future {
resources.take(5)
}
def remove(res:String) = Future {
println(s"Deleting ${res}")
resources = resources.filter( ! _.equals(res) )
}
}
object ResourceTwo {
val resourceDetails = Map("one" ->"oneDetail", "three" -> "threeDetail","four" ->"fourDetails","six" -> "sixDetail", "eight" -> "eightDetail")
def getResourceDetail(resource:String) = {
resourceDetails.get(resource);
}
}
object HelloFuture {
def main(args: Array[String]): Unit = {
println("1. Fetching first five")
val resF = ResourceOne.getFirstFive()
println("2. Retrieving the resource detail from ResourceTwo, if a resourceDetail does not exist then delete the resource from resourceOne")
val resFOut = resF.map( resList => {
resList.map( resOne => {
val resOneDetail = ResourceTwo.getResourceDetail( resOne )
//println(s"Resource details for ${resOne} is ${resOneDetail}")
if( resOneDetail == None) {
println("2.a delete resource if detail is not available")
ResourceOne.remove(resOne)
}
})
})
println("3. Verifying if all the resources retrieved from resourceOne were available in resourceTwo or not.")
//TODO
println("4. If all were not available then retrieve from resourceOne again as the missing ones will have been deleted.")
//TODO
println("5. Repeat step 1 thru 4 till all resources retreived from resourceOne are available in resourceTwo.")
}
}
答案 0 :(得分:0)
环顾四周之后想出了以下解决方案。但是这个问题存在一个小问题,ResourceOne.remove()返回一个未来,下面的实现不能很好地处理它,导致fetchResource()运行几次,直到ResourcesOne.remove()完成。不确定如何处理。
package com.example
import scala.concurrent.Future
import scala.util.{Success,Failure}
import scala.collection.mutable.Map
import scala.concurrent.ExecutionContext.Implicits.global
object ResourceOne {
//var resources = List("one", "two","three","four","five","six","seven","eight","nine")
var resources = List("one", "two","three")
def getFirstFive():Future[List[String]] = Future {
resources.take(5)
}
def remove(res:String) = Future {
println(s"Deleting ${res}")
resources = resources.filter( ! _.equals(res) )
}
}
object ResourceTwo {
val resourceDetails = Map("one" ->"oneDetail", "three" -> "threeDetail","four" ->"fourDetails","six" -> "sixDetail", "eight" -> "eightDetail")
def getResourceDetail(resource:String) = {
resourceDetails.get(resource);
}
}
object HelloFuture {
def main(args: Array[String]): Unit = {
val fOut = fetchResource()
fOut.map{ detail => println("Final Detail retreived is "+ detail) }
}
// Gets from resourceOne and if the detail is not found in resourceTwo then deletes from resourceOne and refetches from resourceOne till both the fetches match
def fetchResource():Future[List[Any]] = {
println("Fetching first five")
val resF = ResourceOne.getFirstFive()
var resOneCount = 0;
val resFOut = resF.map( resList => {
resList.map( resOne => {
val resOneDetail = ResourceTwo.getResourceDetail( resOne )
resOneCount += 1
resOneDetail match {
case Some(_) => { resOneDetail }
case None => { ResourceOne.remove(resOne) ; resOneDetail }
}
})
})
resFOut flatMap {
case x if x.filter(_ != None).size == resOneCount => Future.successful(x)
case _ => { fetchResource() }
}
}
}