1
1
package com .codacy .client .bitbucket .client
2
2
3
+ import java .net .URI
3
4
import java .util .concurrent .{SynchronousQueue , ThreadPoolExecutor , TimeUnit }
4
5
5
6
import com .codacy .client .bitbucket .util .HTTPStatusCodes
7
+ import com .codacy .client .bitbucket .util .Implicits .URIQueryParam
6
8
import com .ning .http .client .AsyncHttpClientConfig
7
9
import play .api .http .{ContentTypeOf , Writeable }
8
10
import play .api .libs .json ._
@@ -26,7 +28,7 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
26
28
*/
27
29
def execute [T ](request : Request [T ])(implicit reader : Reads [T ]): RequestResponse [T ] = {
28
30
get(request.url) match {
29
- case Right (json) => json.validate[T ].fold(_ => FailedResponse (s " Failed to parse json: $json" ), a => SuccessfulResponse (a))
31
+ case Right (json) => json.validate[T ].fold(e => FailedResponse (s " Failed to parse json ( $e ) : $json" ), a => SuccessfulResponse (a))
30
32
case Left (error) => FailedResponse (error.detail)
31
33
}
32
34
}
@@ -35,16 +37,33 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
35
37
* Does a paginated API request and parses the json output into a sequence of classes
36
38
*/
37
39
def executePaginated [T ](request : Request [Seq [T ]])(implicit reader : Reads [T ]): RequestResponse [Seq [T ]] = {
40
+ val FIRST_PAGE = 1
41
+
42
+ def extractValues (json : JsValue ): RequestResponse [Seq [T ]] =
43
+ (json \ " values" ).validate[Seq [T ]].fold(e => FailedResponse (s " Failed to parse json ( $e): $json" ), a => SuccessfulResponse (a))
44
+
38
45
get(request.url) match {
39
46
case Right (json) =>
40
- val nextPage = (json \ " next" ).asOpt[String ]
41
- val nextRepos = nextPage.map {
42
- nextUrl =>
43
- executePaginated(Request (nextUrl, request.classType))
44
- }.getOrElse(SuccessfulResponse (Seq .empty))
45
-
46
- val values = (json \ " values" ).validate[Seq [T ]].fold(_ => FailedResponse (s " Failed to parse json: $json" ), a => SuccessfulResponse (a))
47
- RequestResponse .apply(values, nextRepos)
47
+ val nextPages = (for {
48
+ size <- (json \ " size" ).asOpt[Double ]
49
+ pagelen <- (json \ " pagelen" ).asOpt[Double ]
50
+ } yield {
51
+ val lastPage = math.ceil(size / pagelen).toInt
52
+ (FIRST_PAGE + 1 to lastPage).par.map { page =>
53
+ val nextUrl = new URI (request.url).addQuery(s " page= $page" ).toString
54
+ get(nextUrl) match {
55
+ case Right (json) => extractValues(json)
56
+ case Left (error) => FailedResponse (error.detail)
57
+ }
58
+ }.to[Seq ]
59
+ }).getOrElse(Seq (SuccessfulResponse (Seq .empty)))
60
+
61
+ val values = extractValues(json)
62
+
63
+ (values +: nextPages).foldLeft[RequestResponse [Seq [T ]]](SuccessfulResponse (Seq .empty[T ])) {
64
+ (a, b) =>
65
+ RequestResponse .apply(a, b)
66
+ }
48
67
49
68
case Left (error) =>
50
69
FailedResponse (error.detail)
@@ -153,7 +172,7 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
153
172
case Success (jsValue) =>
154
173
jsValue
155
174
case Failure (e) =>
156
- Left (ResponseError (" Failed to parse json" ,e.getStackTrace.mkString(System .lineSeparator),e.getMessage))
175
+ Left (ResponseError (" Failed to parse json" , e.getStackTrace.mkString(System .lineSeparator), e.getMessage))
157
176
}
158
177
}
159
178
0 commit comments