0

Suppose we have a class which allocates some resources on the heap, and creating it takes some time, so it's hidden behind the future

class Container(val n: Int) {
   allocateMemoryOnTheHeap(n)
   def cleanup(): ???
}
def prepareContainer(val n: Int): Future[Container] = ???

Our task is to download a list of values and put it inside our container class. If any of the downloads failed we want to return a failure and release the resources.

def downloadNumber(): Future[Int] = ???

def numbersProvider(howMany: Int): Future[Seq[Int]] = (0 until howMany).map(downloadNumber).map(Future.sequence)

def prepareContainersForValuesFromUpstream(): Future[Seq[Container]] = {
   val futureNumbers = numbersProvider(42)
   val containersFuture: Future[Seq[Future[Container]]] = futureNumbers.map {
     numbers =>
        numbers.map(prepareContainer(_))
   } 
   containersFuture.flatMap(Future.sequence)
}

def main() = {
   val containersFuture = prepareContainersForValuesFromUpstream()
   val result = Await.result(containersFuture, timeout)
   result match {
      case Success(_) => println("Downloaded values and stored in containers for later!")
      case Failure(_) => //todo: how to release resources from created containers?

   }
}

How can we do it? I think that applying Future.sequence in the prepareContainersForValuesFromUpstream makes it impossible, so we need to address this problem before it. But applying some tricks like this (Scala: List[Future] to Future[List] disregarding failed futures) makes it hard to convert the result to the proper form.

delabania
  • 784
  • 1
  • 5
  • 14
  • If you can use something like **cats-effect**, **ZIO** or **Monix** rather than `Future` then this would be pretty easy. Otherwise, you may use `transformWith` on the final `Future` to ensure the execution of the `cleanup` – Luis Miguel Mejía Suárez Jul 15 '22 at 16:16
  • You can also make container an ADT like data structure, and even if it fails, you’ll have FailedContainer that knows how to cleanup – AminMal Jul 15 '22 at 16:25
  • What specifically is "hadr" about `result.map(_.flatMap(_.toOption))`? – Dima Jul 15 '22 at 16:53
  • You can use `Future#andThen`. See example here (search by `andThen`): https://docs.scala-lang.org/overviews/core/futures.html – Mikhail Ionkin Jul 16 '22 at 12:17

0 Answers0