Skip to content

Commit 1aee061

Browse files
authored
refactor(server): allow injecting bindings cache (#1928)
To improve testability, for the purpose of testing the fix in #1924
1 parent 2daafe1 commit 1aee061

File tree

3 files changed

+46
-18
lines changed

3 files changed

+46
-18
lines changed

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/ArtifactRoutes.kt

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.typesafegithub.workflows.jitbindingserver
22

33
import com.github.benmanes.caffeine.cache.Caffeine
4+
import com.sksamuel.aedile.core.LoadingCache
45
import com.sksamuel.aedile.core.asLoadingCache
56
import com.sksamuel.aedile.core.refreshAfterWrite
67
import io.github.oshai.kotlinlogging.KotlinLogging.logger
@@ -35,41 +36,46 @@ typealias ArtifactResult = Result<Map<String, Artifact>>
3536

3637
private val prefetchScope = CoroutineScope(Dispatchers.IO)
3738

38-
private val bindingsCache =
39+
internal fun buildBindingsCache(): LoadingCache<ActionCoords, ArtifactResult> =
3940
Caffeine
4041
.newBuilder()
4142
.refreshAfterWrite(1.hours)
4243
.recordStats()
4344
.asLoadingCache<ActionCoords, ArtifactResult> { runCatching { it.buildVersionArtifacts()!! } }
4445

45-
fun Routing.artifactRoutes(prometheusRegistry: PrometheusMeterRegistry? = null) {
46+
fun Routing.artifactRoutes(
47+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
48+
prometheusRegistry: PrometheusMeterRegistry? = null,
49+
) {
4650
prometheusRegistry?.let {
4751
CaffeineCacheMetrics.monitor(it, bindingsCache.underlying(), "bindings_cache")
4852
}
4953

5054
route("{owner}/{name}/{version}/{file}") {
51-
artifact(prometheusRegistry, refresh = false)
55+
artifact(prometheusRegistry, bindingsCache, refresh = false)
5256
}
5357

5458
route("/refresh/{owner}/{name}/{version}/{file}") {
55-
artifact(prometheusRegistry, refresh = true)
59+
artifact(prometheusRegistry, bindingsCache, refresh = true)
5660
}
5761
}
5862

5963
private fun Route.artifact(
6064
prometheusRegistry: PrometheusMeterRegistry?,
65+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
6166
refresh: Boolean = false,
6267
) {
63-
headArtifact(prometheusRegistry, refresh)
64-
getArtifact(prometheusRegistry, refresh)
68+
headArtifact(bindingsCache, prometheusRegistry, refresh)
69+
getArtifact(bindingsCache, prometheusRegistry, refresh)
6570
}
6671

6772
private fun Route.headArtifact(
73+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
6874
prometheusRegistry: PrometheusMeterRegistry?,
6975
refresh: Boolean,
7076
) {
7177
head {
72-
val bindingArtifacts = call.toBindingArtifacts(refresh) ?: return@head call.respondNotFound()
78+
val bindingArtifacts = call.toBindingArtifacts(refresh, bindingsCache) ?: return@head call.respondNotFound()
7379

7480
val file = call.parameters["file"] ?: return@head call.respondNotFound()
7581

@@ -84,11 +90,12 @@ private fun Route.headArtifact(
8490
}
8591

8692
private fun Route.getArtifact(
93+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
8794
prometheusRegistry: PrometheusMeterRegistry?,
8895
refresh: Boolean,
8996
) {
9097
get {
91-
val bindingArtifacts = call.toBindingArtifacts(refresh) ?: return@get call.respondNotFound()
98+
val bindingArtifacts = call.toBindingArtifacts(refresh, bindingsCache) ?: return@get call.respondNotFound()
9299

93100
if (refresh && !deliverOnRefreshRoute) return@get call.respondText(text = "OK")
94101

@@ -105,13 +112,19 @@ private fun Route.getArtifact(
105112
}
106113
}
107114

108-
internal fun prefetchBindingArtifacts(coords: Collection<ActionCoords>) {
115+
internal fun prefetchBindingArtifacts(
116+
coords: Collection<ActionCoords>,
117+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
118+
) {
109119
prefetchScope.launch {
110120
bindingsCache.getAll(coords)
111121
}
112122
}
113123

114-
private suspend fun ApplicationCall.toBindingArtifacts(refresh: Boolean): Map<String, Artifact>? {
124+
private suspend fun ApplicationCall.toBindingArtifacts(
125+
refresh: Boolean,
126+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
127+
): Map<String, Artifact>? {
115128
val actionCoords = parameters.extractActionCoords(extractVersion = true)
116129

117130
logger.info { "➡️ Requesting ${actionCoords.prettyPrint}" }

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/Main.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ fun main() {
3838
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
3939
logger.error(throwable) { "Uncaught exception in thread $thread" }
4040
}
41+
val bindingsCache = buildBindingsCache()
4142
embeddedServer(Netty, port = 8080) {
4243
installPlugins(prometheusRegistry)
4344

4445
routing {
4546
internalRoutes(prometheusRegistry)
4647

47-
artifactRoutes(prometheusRegistry)
48-
metadataRoutes(prometheusRegistry)
48+
artifactRoutes(bindingsCache, prometheusRegistry)
49+
metadataRoutes(bindingsCache, prometheusRegistry)
4950
}
5051
}.start(wait = true)
5152
}

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/MetadataRoutes.kt

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.typesafegithub.workflows.jitbindingserver
22

33
import com.github.benmanes.caffeine.cache.Caffeine
4+
import com.sksamuel.aedile.core.LoadingCache
45
import com.sksamuel.aedile.core.asLoadingCache
56
import com.sksamuel.aedile.core.refreshAfterWrite
67
import io.github.oshai.kotlinlogging.KotlinLogging.logger
@@ -21,32 +22,45 @@ private val logger = logger { }
2122

2223
typealias MetadataResult = Result<Map<String, String>>
2324

24-
private val metadataCache =
25+
@Suppress("ktlint:standard:function-signature") // Conflict with detekt.
26+
private fun buildMetadataCache(
27+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
28+
): LoadingCache<ActionCoords, MetadataResult> =
2529
Caffeine
2630
.newBuilder()
2731
.refreshAfterWrite(1.hours)
2832
.recordStats()
2933
.asLoadingCache<ActionCoords, MetadataResult> {
3034
runCatching {
31-
it.buildPackageArtifacts(githubAuthToken = getGithubAuthToken(), ::prefetchBindingArtifacts)
35+
it.buildPackageArtifacts(
36+
githubAuthToken = getGithubAuthToken(),
37+
{ coords -> prefetchBindingArtifacts(coords, bindingsCache) },
38+
)
3239
}
3340
}
3441

35-
fun Routing.metadataRoutes(prometheusRegistry: PrometheusMeterRegistry? = null) {
42+
fun Routing.metadataRoutes(
43+
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
44+
prometheusRegistry: PrometheusMeterRegistry? = null,
45+
) {
46+
val metadataCache = buildMetadataCache(bindingsCache)
3647
prometheusRegistry?.let {
3748
CaffeineCacheMetrics.monitor(it, metadataCache.underlying(), "metadata_cache")
3849
}
3950

4051
route("{owner}/{name}/{file}") {
41-
metadata()
52+
metadata(metadataCache)
4253
}
4354

4455
route("/refresh/{owner}/{name}/{file}") {
45-
metadata(refresh = true)
56+
metadata(metadataCache, refresh = true)
4657
}
4758
}
4859

49-
private fun Route.metadata(refresh: Boolean = false) {
60+
private fun Route.metadata(
61+
metadataCache: LoadingCache<ActionCoords, MetadataResult>,
62+
refresh: Boolean = false,
63+
) {
5064
get {
5165
val actionCoords = call.parameters.extractActionCoords(extractVersion = false)
5266

0 commit comments

Comments
 (0)