Skip to content

Commit f42b6db

Browse files
authored
Improve use in full Kotlin projects (#17)
Improve use in full Kotlin projects (as opposed to standalone Kotlin scripts), especially projects that aren't exclusively about Gradle Enterprise and/or talk to other APIs. - Use a more descriptive name for the global `GradleEnterpriseApi` instance, that doesn't create confusion with other APIs that the project might communicate with. - Allow sharing resources of the internal `OkHttpClient` with another
1 parent 3b62324 commit f42b6db

File tree

7 files changed

+67
-34
lines changed

7 files changed

+67
-34
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A Kotlin library to access the [Gradle Enterprise API][1], easy to use from Kotl
77
scripts:
88

99
```kotlin
10-
api.getBuilds(since = yesterday).forEach {
10+
gradleEnterpriseApi.getBuilds(since = yesterday).forEach {
1111
println(it)
1212
}
1313
```
@@ -28,7 +28,7 @@ API:
2828
@file:Repository("https://jitpack.io")
2929
@file:DependsOn("com.github.gabrielfeo:gradle-enterprise-api-kotlin:1.0")
3030

31-
api.getBuild(id = "hy5nxbzfjxe5k")
31+
gradleEnterpriseApi.getBuild(id = "hy5nxbzfjxe5k")
3232
```
3333

3434
For configuring base URL and token via code and other available options, see the
@@ -69,28 +69,28 @@ for caveats.
6969

7070
API endpoints are provided as a single interface: [`GradleEnterpriseApi`][9]. The Javadoc is a
7171
the same as Gradle's online docs, as they're generated from the same spec. An instance is
72-
initialized and ready-to-use as the global `api` instance:
72+
initialized and ready-to-use as the global `gradleEnterpriseApi` instance:
7373

7474
```kotlin
75-
api.getBuild(id = "hy5nxbzfjxe5k")
75+
gradleEnterpriseApi.getBuild(id = "hy5nxbzfjxe5k")
7676
```
7777

7878
The library also provides a few extension functions on top of the regular API, such as paged
7979
requests and joining. See [`GradleEnterpriseApi` extensions][10].
8080

8181
```kotlin
8282
// Standard query to /api/builds, limited to 1000 builds server-side
83-
api.getBuilds(since = lastMonth)
83+
gradleEnterpriseApi.getBuilds(since = lastMonth)
8484
// Extension: Streams all available builds since given date (paging underneath)
85-
api.getBuildsFlow(since = lastMonth)
85+
gradleEnterpriseApi.getBuildsFlow(since = lastMonth)
8686
```
8787

8888
It's recommended to call [`shutdown()`][11] at the end of scripts to release resources and let the
8989
program exit. Otherwise, it'll keep running for an extra ~60s after code finishes, as an [expected
9090
behavior of OkHttp][4].
9191

9292
```kotlin
93-
val builds = api.getBuilds()
93+
val builds = gradleEnterpriseApi.getBuilds()
9494
// do work ...
9595
shutdown()
9696
```

sample.main.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@file:Repository("https://jitpack.io")
2-
@file:DependsOn("com.github.gabrielfeo:gradle-enterprise-api-kotlin:0.9")
2+
@file:DependsOn("com.github.gabrielfeo:gradle-enterprise-api-kotlin:0.12.0")
33

44
/*
55
* Counts how many developers don't run tests on their local machine
@@ -19,7 +19,7 @@ val oneMonthAgo = LocalDate.now()
1919
runBlocking {
2020

2121
// Filter builds from the API
22-
val buildsByUser = api.getGradleAttributesFlow(since = oneMonthAgo)
22+
val buildsByUser = gradleEnterpriseApi.getGradleAttributesFlow(since = oneMonthAgo)
2323
.filter { "CI" !in it.tags }
2424
.toList()
2525
.groupBy { it.environment.username }

src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/Api.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@
33
package com.gabrielfeo.gradle.enterprise.api
44

55
import com.gabrielfeo.gradle.enterprise.api.internal.*
6-
import java.io.File
7-
import kotlin.time.Duration.Companion.days
86

97
/**
108
* The global instance of [GradleEnterpriseApi].
119
*/
12-
val api: GradleEnterpriseApi by lazy {
10+
val gradleEnterpriseApi: GradleEnterpriseApi by lazy {
1311
retrofit.create(GradleEnterpriseApi::class.java)
1412
}
1513

src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/Options.kt

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package com.gabrielfeo.gradle.enterprise.api
44

55
import com.gabrielfeo.gradle.enterprise.api.internal.*
6+
import okhttp3.Dispatcher
7+
import okhttp3.OkHttpClient
68
import java.io.File
79
import kotlin.time.Duration.Companion.days
810

@@ -12,8 +14,8 @@ import kotlin.time.Duration.Companion.days
1214
val options = Options(env = RealEnv, keychain = RealKeychain(RealEnv))
1315

1416
/**
15-
* Library configuration options. Should not be changed after accessing the [api] object for the
16-
* first time.
17+
* Library configuration options. Should not be changed after accessing the [gradleEnterpriseApi]
18+
* object for the first time.
1719
*
1820
* Use the global [options] instance.
1921
*/
@@ -23,14 +25,14 @@ class Options internal constructor(
2325
) {
2426

2527
val gradleEnterpriseInstance = GradleEnterpriseInstanceOptions(env, keychain)
26-
val concurrency = ConcurrencyOptions(env)
28+
val httpClient = HttpClientOptions(env)
2729
val cache = CacheOptions(env)
2830
val debugging = DebuggingOptions(env)
2931

3032
/**
3133
* Options about the GE instance, such as URL and API token.
3234
*
33-
* Access via the global [options] instance.
35+
* Access via the global [options] instance: `options.gradleEnterpriseInstance`.
3436
*/
3537
class GradleEnterpriseInstanceOptions internal constructor(
3638
private val env: Env,
@@ -58,31 +60,45 @@ class Options internal constructor(
5860
}
5961

6062
/**
61-
* Concurrency options.
63+
* HTTP client options.
6264
*
63-
* Access via the global [options] instance.
65+
* Access via the global [options] instance: `options.httpClient`.
6466
*/
65-
class ConcurrencyOptions internal constructor(
67+
class HttpClientOptions internal constructor(
6668
env: Env,
6769
) {
6870

71+
/**
72+
* Provider of an [OkHttpClient.Builder] to use when building the library's internal client.
73+
* Has a default value and shouldn't be needed in scripts.
74+
*
75+
* This is aimed at using the library inside a full Kotlin project. Allows the internal client to
76+
* share resources such as thread pools with another [OkHttpClient], useful for full Kotlin projects
77+
* and rarely needed for scripting. See [OkHttpClient] for all that is shared.
78+
*/
79+
var clientBuilder: () -> OkHttpClient.Builder = {
80+
OkHttpClient.Builder()
81+
}
82+
6983
/**
7084
* Maximum amount of concurrent requests allowed. Further requests will be queued. By default,
71-
* uses environment variable `GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS` or 15.
85+
* uses environment variable `GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS` or 5 (OkHttp's
86+
* default value of [Dispatcher.maxRequestsPerHost]).
7287
*
73-
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-dispatcher
88+
* If set, will set [Dispatcher.maxRequests] and [Dispatcher.maxRequestsPerHost] of the
89+
* internal client, overwriting what's inherited from the base client of [clientBuilder],
90+
* if any.
7491
*/
7592
var maxConcurrentRequests =
7693
env["GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS"]?.toInt()
77-
?: 15
7894
}
7995

8096
/**
8197
* HTTP cache is off by default, but can speed up requests significantly. The Gradle Enterprise
8298
* API disallows HTTP caching, but this library forcefully enables it by overwriting
8399
* cache-related headers in API responses. Enable with [cacheEnabled].
84100
*
85-
* Access via the global [options] instance.
101+
* Access via the global [options] instance: `options.cache`.
86102
*
87103
* Responses can be:
88104
*
@@ -197,7 +213,7 @@ class Options internal constructor(
197213
/**
198214
* Library debugging options.
199215
*
200-
* Access via the global [options] instance.
216+
* Access via the global [options] instance: `options.debugging`.
201217
*/
202218
class DebuggingOptions internal constructor(
203219
env: Env,

src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/internal/OkHttpClient.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import com.gabrielfeo.gradle.enterprise.api.internal.auth.HttpBearerAuth
55
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheEnforcingInterceptor
66
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheHitLoggingInterceptor
77
import okhttp3.Cache
8-
import okhttp3.OkHttpClient
98
import java.util.logging.Level
109
import java.util.logging.Logger
1110

@@ -15,7 +14,7 @@ internal val okHttpClient by lazy {
1514

1615
internal fun buildOkHttpClient(
1716
options: Options,
18-
) = with(OkHttpClient.Builder()) {
17+
) = with(options.httpClient.clientBuilder()) {
1918
if (options.cache.cacheEnabled) {
2019
cache(buildCache(options))
2120
}
@@ -27,8 +26,10 @@ internal fun buildOkHttpClient(
2726
addNetworkInterceptor(buildCacheEnforcingInterceptor(options))
2827
}
2928
build().apply {
30-
dispatcher.maxRequests = options.concurrency.maxConcurrentRequests
31-
dispatcher.maxRequestsPerHost = options.concurrency.maxConcurrentRequests
29+
options.httpClient.maxConcurrentRequests?.let {
30+
dispatcher.maxRequests = it
31+
dispatcher.maxRequestsPerHost = it
32+
}
3233
}
3334
}
3435

src/test/kotlin/com/gabrielfeo/gradle/enterprise/api/OkHttpClientTest.kt

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
package com.gabrielfeo.gradle.enterprise.api
22

3-
import com.gabrielfeo.gradle.enterprise.api.internal.Env
43
import com.gabrielfeo.gradle.enterprise.api.internal.FakeEnv
54
import com.gabrielfeo.gradle.enterprise.api.internal.FakeKeychain
65
import com.gabrielfeo.gradle.enterprise.api.internal.auth.HttpBearerAuth
76
import com.gabrielfeo.gradle.enterprise.api.internal.buildOkHttpClient
87
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheEnforcingInterceptor
98
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheHitLoggingInterceptor
10-
import okhttp3.Interceptor
9+
import okhttp3.Dispatcher
1110
import okhttp3.OkHttpClient
12-
import kotlin.reflect.KClass
1311
import kotlin.test.*
1412

1513
class OkHttpClientTest {
@@ -21,14 +19,28 @@ class OkHttpClientTest {
2119
}
2220

2321
@Test
24-
fun `Sets max concurrency from options`() {
22+
fun `Given maxConcurrentRequests, sets values in Dispatcher`() {
2523
val client = buildClient(
2624
"GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS" to "123"
2725
)
2826
assertEquals(123, client.dispatcher.maxRequests)
2927
assertEquals(123, client.dispatcher.maxRequestsPerHost)
3028
}
3129

30+
@Test
31+
fun `Given no maxConcurrentRequests, preserves original client's Dispatcher values`() {
32+
val baseClient = OkHttpClient.Builder()
33+
.dispatcher(
34+
Dispatcher().apply {
35+
maxRequests = 1
36+
maxRequestsPerHost = 1
37+
}
38+
).build()
39+
val client = buildClient(clientBuilder = baseClient.newBuilder())
40+
assertEquals(1, client.dispatcher.maxRequests)
41+
assertEquals(1, client.dispatcher.maxRequestsPerHost)
42+
}
43+
3244
@Test
3345
fun `Given debug logging and cache enabled, adds logging interceptors`() {
3446
val client = buildClient(
@@ -64,12 +76,18 @@ class OkHttpClientTest {
6476

6577
private fun buildClient(
6678
vararg envVars: Pair<String, String?>,
79+
clientBuilder: OkHttpClient.Builder? = null,
6780
): OkHttpClient {
6881
val env = FakeEnv(*envVars)
6982
if ("GRADLE_ENTERPRISE_API_TOKEN" !in env)
7083
env["GRADLE_ENTERPRISE_API_TOKEN"] = "example-token"
7184
if ("GRADLE_ENTERPRISE_API_URL" !in env)
7285
env["GRADLE_ENTERPRISE_API_URL"] = "example-url"
73-
return buildOkHttpClient(Options(env, FakeKeychain()))
86+
val options = Options(env, FakeKeychain()).apply {
87+
clientBuilder?.let {
88+
httpClient.clientBuilder = { it }
89+
}
90+
}
91+
return buildOkHttpClient(options)
7492
}
7593
}

src/test/kotlin/com/gabrielfeo/gradle/enterprise/api/OptionsTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class OptionsTest {
6464
env = FakeEnv("GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS" to "1"),
6565
)
6666
assertDoesNotThrow {
67-
options.concurrency.maxConcurrentRequests
67+
options.httpClient.maxConcurrentRequests
6868
}
6969
}
7070

0 commit comments

Comments
 (0)