Основная проблема, с которой вы здесь сталкиваетесь, заключается в том, что вы пытаетесь объединить данные, которые у вас уже есть (List[MergeRequest]
), с данными, которые вы получите в будущем (Future[List[MergeRequest]]
).Есть несколько вещей, которые вам нужно сделать, чтобы справиться с этим сценарием:
- Используйте
flatMap
вместо map
в результате запроса HTTP.Это позволяет вам делать дополнительные HTTP-запросы внутри рекурсии, но отображать их обратно на один Future
. - Вызов
map
по результату рекурсии fetchMergeRequests(nextPage)
для объединения данных, которые у вас уже есть, сбудущие данные из рекурсии. - Оберните другой список в
Future.successful()
, поскольку flatMap
требует, чтобы все совпадения с образцом возвращали Future
- за исключением исключения.
Я не знаком с библиотеками, которые вы используете, поэтому я не проверял их, но я думаю, что ваш код должен работать так:
def fetchMergeRequests(startPage: Int = 1): Future[List[MergeRequest]] = {
val requestsUrl = url(s"https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab-ce/merge_requests?state=opened&per_page=3&page=${startPage}")
Http(requestsUrl).flatMap { res =>
(parse(res.getResponseBody), res.getHeader("X-Next-Page").toInt) match {
case (list@JArray(_), nextPage: Int) =>
val currentList: List[MergeRequest] = MergeRequest.parseList(list).get
val nextPageListFuture: Future[List[MergeRequest]] = fetchMergeRequests(nextPage)
nextPageListFuture.map(nextPageList => currentList ++ nextPageList)
case (list@JArray(_), _) =>
Future.successful(MergeRequest.parseList(list).get)
case _ => throw new RuntimeException(s"No merge requests for project found")
}
}
}