Tail recursion to get data from paginated get API

Viewed 51

Some APIs offers paginated data. I want to call the API and retrieve the data of all pages. I was thinking an implementation of it using recursion. I will call it to retrieve the first page data and the url of next page. If next page is empty it means there's no more data to retrieve.

I have this code, which is not really calling an API but it is useful to implement the recursive function I need. The issue I'm facing is that I can't add the tailrec annotation, I can't transform it to be tail recursive.

How can I achieve it?

Code for simulating the API which return results in pages:

final case class Response(data: List[Int], nextUrl: Option[String])

object Api {
  def getNumbers(url: String): Future[Response] = {
    url match {
      case "1" => Future.successful(Response(List(1, 2), Option("2")))
      case "2" => Future.successful(Response(List(3, 4), Option("3")))
      case "3" => Future.successful(Response(List(5, 6), None))
      case _   => Future.failed(new RuntimeException("Error!"))
    }
  }
}

Function/method to call the API, which I want to convert it to tail recursion:

  def getPaginatedData(url: String): Future[Seq[Int]] = {

    //    @tailrec
    def loop(url: String, acc: Seq[Int]): Future[Seq[Int]] = {
      Api.getNumbers(url).flatMap { response =>
        response.nextUrl match {
          case None       => Future.successful(acc ++ response.data)
          case Some(link) => loop(link, acc ++ response.data)
        }
      }
    }

    loop(url, List.empty)
  }

To run the example:

  def main(args: Array[String]): Unit = {
    SomeService.getPaginatedData("1").onComplete {
      case Failure(e)     => println(s"Error! $e")
      case Success(value) => println(value)
    }
  }
0 Answers
Related