Skip to content

Commit 370ab1c

Browse files
authored
Support advanced query in BuildsApi extensions (#126)
Advanced query is supported in the GE API from 2023.3 as the `query` parameter in `BuildsApi.getBuilds`. Extensions should support the same parameters, including `query`. This parameter allows for server-side filtering, which can make querying the API significantly faster. Also rename some files to prepare for the next PR.
1 parent 8d51055 commit 370ab1c

File tree

4 files changed

+54
-21
lines changed

4 files changed

+54
-21
lines changed

library/src/integrationTest/kotlin/com/gabrielfeo/gradle/enterprise/api/internal/GradleEnterpriseApiIntegrationTest.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.gabrielfeo.gradle.enterprise.api.internal
33
import com.gabrielfeo.gradle.enterprise.api.Config
44
import com.gabrielfeo.gradle.enterprise.api.GradleEnterpriseApi
55
import kotlinx.coroutines.test.runTest
6+
import okhttp3.HttpUrl.Companion.toHttpUrl
67
import org.junit.jupiter.api.assertDoesNotThrow
78
import kotlin.test.assertEquals
89
import kotlin.test.Test
@@ -14,8 +15,12 @@ class GradleEnterpriseApiIntegrationTest {
1415
env = RealEnv
1516
keychain = RealKeychain(RealSystemProperties)
1617
val api = GradleEnterpriseApi.newInstance()
17-
val builds = api.buildsApi.getBuilds(since = 0, maxBuilds = 1)
18-
assertEquals(1, builds.size)
18+
val builds = api.buildsApi.getBuilds(
19+
since = 0,
20+
maxBuilds = 5,
21+
query = """tag:local value:"Email=gabriel.feo*""""
22+
)
23+
assertEquals(5, builds.size)
1924
api.shutdown()
2025
}
2126

library/src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/extension/BuildsApiExtensions.kt

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
package com.gabrielfeo.gradle.enterprise.api.extension
44

5+
import com.gabrielfeo.gradle.enterprise.api.Config
56
import com.gabrielfeo.gradle.enterprise.api.BuildsApi
67
import com.gabrielfeo.gradle.enterprise.api.internal.API_MAX_BUILDS
78
import com.gabrielfeo.gradle.enterprise.api.internal.operator.pagedUntilLastBuild
8-
import com.gabrielfeo.gradle.enterprise.api.internal.operator.withGradleAttributes
99
import com.gabrielfeo.gradle.enterprise.api.model.*
1010
import kotlinx.coroutines.CoroutineScope
1111
import kotlinx.coroutines.DelicateCoroutinesApi
@@ -17,15 +17,21 @@ import kotlinx.coroutines.flow.*
1717
* for queries of any size, as opposed to [BuildsApi.getBuilds] which is limited by the
1818
* API itself to 1000.
1919
*
20-
* - Will request from the API until results end or an error occurs.
21-
* - Use [Sequence.take] and similar functions to stop collecting early.
22-
* - A subset of `getBuilds` params are supported
20+
* - Will request from the API until results end, collection stops or an error occurs.
21+
* - Parameters same as [BuildsApi.getBuilds].
22+
* - Using [query] is highly recommended for server-side filtering (equivalent to GE advanced
23+
* query).
24+
* - `maxBuilds` is the only unsupported parameter, because this Flow will instead fetch
25+
* continously. Use [Flow.take] to stop collecting at a specific count.
2326
*/
2427
fun BuildsApi.getBuildsFlow(
2528
since: Long = 0,
2629
sinceBuild: String? = null,
2730
fromInstant: Long? = null,
2831
fromBuild: String? = null,
32+
query: String? = null,
33+
reverse: Boolean? = null,
34+
maxWaitSecs: Int? = null,
2935
buildsPerPage: Int = API_MAX_BUILDS,
3036
): Flow<Build> {
3137
val api = this
@@ -35,6 +41,9 @@ fun BuildsApi.getBuildsFlow(
3541
sinceBuild = sinceBuild,
3642
fromInstant = fromInstant,
3743
fromBuild = fromBuild,
44+
query = query,
45+
reverse = reverse,
46+
maxWaitSecs = maxWaitSecs,
3847
maxBuilds = buildsPerPage,
3948
)
4049
val pagedBuilds = firstBuilds.asFlow().pagedUntilLastBuild(api, buildsPerPage)
@@ -43,13 +52,20 @@ fun BuildsApi.getBuildsFlow(
4352
}
4453

4554
/**
46-
* Gets [GradleAttributes] of all builds from a given date. Queries [BuildsApi.getBuilds]
47-
* first, since it's the only endpoint providing a timeline of builds, then maps each to
48-
* [BuildsApi.getGradleAttributes].
55+
* Gets [GradleAttributes] of all builds from a given date. Queries [BuildsApi.getBuilds] first,
56+
* the endpoint providing a timeline of builds, then maps each to [BuildsApi.getGradleAttributes].
4957
*
50-
* Don't expect client-side filtering to be efficient. Will request up to [Int.MAX_VALUE]
51-
* builds and their attributes concurrently and eagerly, with a buffer, in coroutines started in
52-
* [scope]. For other params, see [getBuildsFlow] and [BuildsApi.getBuilds].
58+
* Instead of filtering builds downstream based on `GradleAttributes` (e.g. using [Flow.filter]),
59+
* prefer filtering server-side using a `query` (see [BuildsApi.getBuilds]).
60+
*
61+
* ### Buffering
62+
*
63+
* Will request eagerly and buffer up to [Int.MAX_VALUE] calls.
64+
*
65+
* ### Concurrency
66+
*
67+
* Attributes are requested concurrently in coroutines started in [scope]. The number of
68+
* concurrent requests underneath is still limited by [Config.maxConcurrentRequests].
5369
*
5470
* @param scope CoroutineScope in which to create coroutines. Defaults to [GlobalScope].
5571
*/
@@ -59,13 +75,19 @@ fun BuildsApi.getGradleAttributesFlow(
5975
sinceBuild: String? = null,
6076
fromInstant: Long? = null,
6177
fromBuild: String? = null,
78+
query: String? = null,
79+
reverse: Boolean? = null,
80+
maxWaitSecs: Int? = null,
6281
scope: CoroutineScope = GlobalScope,
6382
): Flow<GradleAttributes> =
6483
getBuildsFlow(
6584
since = since,
6685
sinceBuild = sinceBuild,
6786
fromInstant = fromInstant,
68-
fromBuild = fromBuild
87+
fromBuild = fromBuild,
88+
query = query,
89+
reverse = reverse,
90+
maxWaitSecs = maxWaitSecs,
6991
).withGradleAttributes(scope, api = this).map { (_, attrs) ->
7092
attrs
7193
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.gabrielfeo.gradle.enterprise.api.internal.operator
1+
package com.gabrielfeo.gradle.enterprise.api.extension
22

33
import com.gabrielfeo.gradle.enterprise.api.*
44
import com.gabrielfeo.gradle.enterprise.api.model.*
Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
package com.gabrielfeo.gradle.enterprise.api.internal.operator
1+
package com.gabrielfeo.gradle.enterprise.api.extension
22

33
import com.gabrielfeo.gradle.enterprise.api.FakeBuildsApi
44
import com.gabrielfeo.gradle.enterprise.api.model.FakeBuild
5-
import kotlinx.coroutines.*
6-
import kotlinx.coroutines.flow.*
5+
import kotlinx.coroutines.ExperimentalCoroutinesApi
6+
import kotlinx.coroutines.Job
7+
import kotlinx.coroutines.flow.asFlow
8+
import kotlinx.coroutines.flow.collect
9+
import kotlinx.coroutines.flow.take
10+
import kotlinx.coroutines.flow.toList
11+
import kotlinx.coroutines.launch
712
import kotlinx.coroutines.test.runTest
13+
import kotlinx.coroutines.withTimeoutOrNull
814
import org.junit.jupiter.api.Test
915
import kotlin.test.assertEquals
1016
import kotlin.time.Duration.Companion.seconds
1117

1218
@OptIn(ExperimentalCoroutinesApi::class)
13-
class WithGradleAttributesTest {
19+
class MappingTest {
1420

1521
private val api = FakeBuildsApi(
1622
builds = listOf(
@@ -23,7 +29,7 @@ class WithGradleAttributesTest {
2329
)
2430

2531
@Test
26-
fun `Pairs each build with its GradleAttributes`() = runTest {
32+
fun `withGradleAttributes pairs each build with its GradleAttributes`() = runTest {
2733
val buildsToAttrs = api.builds.asFlow().withGradleAttributes(scope = this, api).toList()
2834
assertEquals(5, api.getGradleAttributesCallCount.value)
2935
assertEquals(5, buildsToAttrs.size)
@@ -33,7 +39,7 @@ class WithGradleAttributesTest {
3339
}
3440

3541
@Test
36-
fun `Fetches GradleAttributes for all builds eagerly`() = runTest {
42+
fun `withGradleAttributes fetches GradleAttributes for all builds eagerly`() = runTest {
3743
backgroundScope.launch {
3844
api.builds.asFlow().withGradleAttributes(scope = this, api).collect {
3945
// Make the first collect never complete, simulating a slow collector
@@ -46,4 +52,4 @@ class WithGradleAttributesTest {
4652
}
4753
assertEquals(5, api.getGradleAttributesCallCount.value)
4854
}
49-
}
55+
}

0 commit comments

Comments
 (0)