1
1
package com.gabrielfeo.gradle.enterprise.api
2
2
3
+ import com.gabrielfeo.gradle.enterprise.api.internal.API_MAX_BUILDS
4
+ import com.gabrielfeo.gradle.enterprise.api.internal.operator.pagedUntilLastBuild
5
+ import com.gabrielfeo.gradle.enterprise.api.internal.operator.withGradleAttributes
3
6
import com.gabrielfeo.gradle.enterprise.api.model.*
4
7
import kotlinx.coroutines.CoroutineScope
8
+ import kotlinx.coroutines.DelicateCoroutinesApi
5
9
import kotlinx.coroutines.GlobalScope
6
- import kotlinx.coroutines.async
7
10
import kotlinx.coroutines.flow.*
8
11
import retrofit2.await
9
12
10
- private const val API_MAX_BUILDS = 1000
11
-
12
13
/* *
13
14
* Gets builds on demand from the API, in as many requests as necessary. It allows
14
15
* for queries of any size, as opposed to [GradleEnterpriseApi.getBuilds] which is limited by the
@@ -24,43 +25,17 @@ fun GradleEnterpriseApi.getBuildsFlow(
24
25
fromInstant : Long? = null,
25
26
fromBuild : String? = null,
26
27
): Flow <Build > = flow {
27
- var lastBuildId: String? = null
28
- while (true ) {
29
- val call = when (lastBuildId) {
30
- null -> getBuilds(
31
- since = since, sinceBuild = sinceBuild,
32
- fromInstant = fromInstant, fromBuild = fromBuild,
33
- maxBuilds = API_MAX_BUILDS ,
34
- )
35
- else -> getBuilds(fromBuild = lastBuildId, maxBuilds = API_MAX_BUILDS )
36
- }
37
- val builds = call.await()
38
- emitAll(builds.asFlow())
39
- when {
40
- builds.isEmpty() || builds.size < API_MAX_BUILDS -> break
41
- else -> lastBuildId = builds.last().id
42
- }
43
- }
28
+ val firstBuilds = getBuilds(
29
+ since = since,
30
+ sinceBuild = sinceBuild,
31
+ fromInstant = fromInstant,
32
+ fromBuild = fromBuild,
33
+ maxBuilds = API_MAX_BUILDS ,
34
+ ).await()
35
+ val pagedBuilds = firstBuilds.asFlow().pagedUntilLastBuild(maxPerRequest = API_MAX_BUILDS )
36
+ emitAll(pagedBuilds)
44
37
}
45
38
46
- /* *
47
- * Joins builds with their [GradleAttributes], which comes from a different endpoint
48
- * ([GradleEnterpriseApi.getGradleAttributes]).
49
- *
50
- * Don't expect client-side filtering to be efficient. Does as many concurrent calls
51
- * as it can, requesting attributes in an eager coroutine, in [scope].
52
- */
53
- fun Flow<Build>.withGradleAttributes (
54
- scope : CoroutineScope = GlobalScope ,
55
- ): Flow <Pair <Build , GradleAttributes >> =
56
- map { build ->
57
- build to scope.async {
58
- api.getGradleAttributes(build.id).await()
59
- }
60
- }.buffer(Int .MAX_VALUE ).map { (build, attrs) ->
61
- build to attrs.await()
62
- }
63
-
64
39
/* *
65
40
* Gets [GradleAttributes] of all builds from a given date. Queries [GradleEnterpriseApi.getBuilds]
66
41
* first, since it's the only endpoint providing a timeline of builds, then maps each to
@@ -69,7 +44,10 @@ fun Flow<Build>.withGradleAttributes(
69
44
* Don't expect client-side filtering to be efficient. Does as many concurrent calls
70
45
* as it can, requesting attributes in an eager coroutine, in [scope]. For other params,
71
46
* see [getBuildsFlow] and [GradleEnterpriseApi.getBuilds].
47
+ *
48
+ * @param scope CoroutineScope in which to create coroutines. Defaults to [GlobalScope].
72
49
*/
50
+ @OptIn(DelicateCoroutinesApi ::class )
73
51
fun GradleEnterpriseApi.getGradleAttributesFlow (
74
52
since : Long = 0,
75
53
sinceBuild : String? = null,
0 commit comments