1
1
package com .codacy .client .bitbucket .client
2
2
3
+ import java .util .concurrent .{SynchronousQueue , ThreadPoolExecutor , TimeUnit }
4
+
3
5
import com .codacy .client .bitbucket .util .HTTPStatusCodes
4
- import com .ning .http .client .AsyncHttpClient
6
+ import com .ning .http .client .AsyncHttpClientConfig
5
7
import play .api .libs .json .{JsValue , Json , Reads }
6
8
import play .api .libs .oauth ._
7
- import play .api .libs .ws .ning .NingWSClient
9
+ import play .api .libs .ws .DefaultWSClientConfig
10
+ import play .api .libs .ws .ning .{NingAsyncHttpClientConfigBuilder , NingWSClient }
8
11
9
12
import scala .concurrent .Await
10
13
import scala .concurrent .duration .{Duration , SECONDS }
14
+ import scala .util .{Failure , Properties , Success , Try }
11
15
12
16
class BitbucketClient (key : String , secretKey : String , token : String , secretToken : String ) {
13
17
@@ -50,9 +54,7 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
50
54
/*
51
55
* Does an API post
52
56
*/
53
- def post [T ](request : Request [T ], values : JsValue )(implicit reader : Reads [T ]): RequestResponse [T ] = {
54
- val client = new NingWSClient (new AsyncHttpClient ().getConfig)
55
-
57
+ def post [T ](request : Request [T ], values : JsValue )(implicit reader : Reads [T ]): RequestResponse [T ] = withClientRequest { client =>
56
58
val jpromise = client.url(request.url)
57
59
.sign(requestSigner)
58
60
.withFollowRedirects(follow = true )
@@ -73,14 +75,11 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
73
75
RequestResponse [T ](None , result.statusText, hasError = true )
74
76
}
75
77
76
- client.close()
77
78
value
78
79
}
79
80
80
81
/* copy paste from post ... */
81
- def delete [T ](url : String ): RequestResponse [Boolean ] = {
82
- val client = new NingWSClient (new AsyncHttpClient ().getConfig)
83
-
82
+ def delete [T ](url : String ): RequestResponse [Boolean ] = withClientRequest { client =>
84
83
val jpromise = client.url(url)
85
84
.sign(requestSigner)
86
85
.withFollowRedirects(follow = true )
@@ -93,13 +92,10 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
93
92
RequestResponse [Boolean ](None , result.statusText, hasError = true )
94
93
}
95
94
96
- client.close()
97
95
value
98
96
}
99
97
100
- private def get (url : String ): Either [ResponseError , JsValue ] = {
101
- val client = new NingWSClient (new AsyncHttpClient ().getConfig)
102
-
98
+ private def get (url : String ): Either [ResponseError , JsValue ] = withClientEither { client =>
103
99
val jpromise = client.url(url)
104
100
.sign(requestSigner)
105
101
.withFollowRedirects(follow = true )
@@ -113,7 +109,6 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
113
109
Left (ResponseError (java.util.UUID .randomUUID().toString, result.statusText, result.statusText))
114
110
}
115
111
116
- client.close()
117
112
value
118
113
}
119
114
@@ -127,4 +122,45 @@ class BitbucketClient(key: String, secretKey: String, token: String, secretToken
127
122
Left (error)
128
123
}.getOrElse(Right (json))
129
124
}
125
+
126
+ private def withClientEither [T ](block : NingWSClient => Either [ResponseError , T ]): Either [ResponseError , T ] = {
127
+ withClient(block) match {
128
+ case Success (res) => res
129
+ case Failure (error) =>
130
+ Left (ResponseError (" Request failed" , getFullStackTrace(error), error.getMessage))
131
+ }
132
+ }
133
+
134
+ private def withClientRequest [T ](block : NingWSClient => RequestResponse [T ]): RequestResponse [T ] = {
135
+ withClient(block) match {
136
+ case Success (res) => res
137
+ case Failure (error) =>
138
+ val statusMessage =
139
+ s """
140
+ |Failed request:
141
+ |
142
+ | ${getFullStackTrace(error)}
143
+ """ .stripMargin
144
+ RequestResponse [T ](None , statusMessage, hasError = true )
145
+ }
146
+ }
147
+
148
+ private def withClient [T ](block : NingWSClient => T ): Try [T ] = {
149
+ val config = new NingAsyncHttpClientConfigBuilder (DefaultWSClientConfig ()).build()
150
+ val clientConfig = new AsyncHttpClientConfig .Builder (config)
151
+ .setExecutorService(new ThreadPoolExecutor (0 , 2 , 30L , TimeUnit .SECONDS , new SynchronousQueue [Runnable ]))
152
+ .build()
153
+ val client = new NingWSClient (clientConfig)
154
+ val result = Try (block(client))
155
+ client.close()
156
+ result
157
+ }
158
+
159
+ private def getFullStackTrace (throwableOpt : Throwable , accumulator : String = " " ): String = {
160
+ Option (throwableOpt).map { throwable =>
161
+ val newAccumulator = s " $accumulator${Properties .lineSeparator}${throwable.getStackTraceString}"
162
+ getFullStackTrace(throwable.getCause, newAccumulator)
163
+ }.getOrElse(accumulator)
164
+ }
165
+
130
166
}
0 commit comments