Skip to content

Commit

Permalink
Move options to an object
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielfeo committed Jan 3, 2023
1 parent 611c406 commit 5905c5f
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 124 deletions.
95 changes: 0 additions & 95 deletions src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,6 @@ val api: GradleEnterpriseApi by lazy {
retrofit.create(GradleEnterpriseApi::class.java)
}

/**
* Provides the URL of a Gradle Enterprise API instance. By default, uses environment variable
* `GRADLE_ENTERPRISE_URL`.
*/
var baseUrl: () -> String = {
requireBaseUrl(envName = "GRADLE_ENTERPRISE_URL")
}

/**
* Provides the access token for a Gradle Enterprise API instance. By default, uses keychain entry
* `gradle-enterprise-api-token` or environment variable `GRADLE_ENTERPRISE_URL`.
*/
var accessToken: () -> String = {
requireToken(
keychainName = "gradle-enterprise-api-token",
envName = "GRADLE_ENTERPRISE_API_TOKEN",
)
}

/**
* Shutdown the internal client, releasing resources and allowing the program to
* finish before the client's idle timeout.
Expand All @@ -45,79 +26,3 @@ fun shutdown() {
cache?.close();
}
}

/**
* Regex pattern to match API URLs that are OK to store long-term in the HTTP cache, up to
* [longTermCacheMaxAge] (1y by default, max value). By default, uses environment variable
* `GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_URL_PATTERN` or a pattern matching:
* - {host}/api/builds/{id}/gradle-attributes
* - {host}/api/builds/{id}/maven-attributes
*
* Gradle Enterprise API disallows HTTP caching, but this library forcefully removes such
* restriction.
*
* Use `|` to define multiple patterns in one, e.g. `.*gradle-attributes|.*test-distribution`.
*/
var longTermCacheUrlPattern: Regex =
System.getenv("GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_URL_PATTERN")?.toRegex()
?: """.*/api/builds/[\d\w]+/(?:gradle|maven)-attributes""".toRegex()

/**
* Max age in seconds for URLs to be cached long-term (matched by [longTermCacheUrlPattern]).
* By default, uses environment variable `GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_MAX_AGE` or 1 year.
*/
var longTermCacheMaxAge: Long =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE")?.toLong()
?: 365.days.inWholeSeconds

/**
* Regex pattern to match API URLs that are OK to store short-term in the HTTP cache, up to
* [shortTermCacheMaxAge] (1d by default). By default, uses environment variable
* `GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_URL_PATTERN` or a pattern matching:
* - {host}/api/builds
*
* Gradle Enterprise API disallows HTTP caching, but this library forcefully removes such
* restriction.
*
* Use `|` to define multiple patterns in one, e.g. `.*gradle-attributes|.*test-distribution`.
*/
var shortTermCacheUrlPattern: Regex =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_URL_PATTERN")?.toRegex()
?: """.*/builds(?:\?.*|\Z)""".toRegex()

/**
* Max age in seconds for URLs to be cached short-term (matched by [shortTermCacheUrlPattern]).
* By default, uses environment variable `GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE` or 1 day.
*/
var shortTermCacheMaxAge: Long =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE")?.toLong()
?: 1.days.inWholeSeconds

/**
* Maximum amount of concurrent requests allowed. Further requests will be queued. By default,
* uses environment variable `GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS` or 15.
*
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-dispatcher
*/
var maxConcurrentRequests = System.getenv("GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS")?.toInt()
?: 15

/**
* Max size of the HTTP cache. By default, uses environment variable
* `GRADLE_ENTERPRISE_API_MAX_CACHE_SIZE` or ~1 GB.
*/
var maxCacheSize = System.getenv("GRADLE_ENTERPRISE_API_MAX_CACHE_SIZE")?.toLong()
?: 1_000_000_000L

/**
* HTTP cache location. By default, uses environment variable `GRADLE_ENTERPRISE_API_CACHE_DIR`
* or the system temporary folder (`java.io.tmpdir` / gradle-enterprise-api-kotlin-cache).
*/
var cacheDir = System.getenv("GRADLE_ENTERPRISE_API_CACHE_DIR")?.let(::File)
?: File(System.getProperty("java.io.tmpdir"), "gradle-enterprise-api-kotlin-cache")

/**
* Enables debug logging from the library. All logging is output to stderr. By default, uses
* environment variable `GRADLE_ENTERPRISE_API_DEBUG_LOGGING` or `false`.
*/
var debugLoggingEnabled = System.getenv("GRADLE_ENTERPRISE_API_DEBUG_LOGGING").toBoolean()
108 changes: 108 additions & 0 deletions src/main/kotlin/com/gabrielfeo/gradle/enterprise/api/Options.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package com.gabrielfeo.gradle.enterprise.api

import com.gabrielfeo.gradle.enterprise.api.internal.requireBaseUrl
import com.gabrielfeo.gradle.enterprise.api.internal.requireToken
import java.io.File
import kotlin.time.Duration.Companion.days

object Options {

/**
* Provides the URL of a Gradle Enterprise API instance. By default, uses environment variable
* `GRADLE_ENTERPRISE_URL`.
*/
var baseUrl: () -> String = {
requireBaseUrl(envName = "GRADLE_ENTERPRISE_URL")
}

/**
* Provides the access token for a Gradle Enterprise API instance. By default, uses keychain entry
* `gradle-enterprise-api-token` or environment variable `GRADLE_ENTERPRISE_URL`.
*/
var accessToken: () -> String = {
requireToken(
keychainName = "gradle-enterprise-api-token",
envName = "GRADLE_ENTERPRISE_API_TOKEN",
)
}

/**
* Maximum amount of concurrent requests allowed. Further requests will be queued. By default,
* uses environment variable `GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS` or 15.
*
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-dispatcher
*/
var maxConcurrentRequests =
System.getenv("GRADLE_ENTERPRISE_API_MAX_CONCURRENT_REQUESTS")?.toInt()
?: 15

/**
* HTTP cache location. By default, uses environment variable `GRADLE_ENTERPRISE_API_CACHE_DIR`
* or the system temporary folder (`java.io.tmpdir` / gradle-enterprise-api-kotlin-cache).
*/
var cacheDir =
System.getenv("GRADLE_ENTERPRISE_API_CACHE_DIR")?.let(::File)
?: File(System.getProperty("java.io.tmpdir"), "gradle-enterprise-api-kotlin-cache")

/**
* Max size of the HTTP cache. By default, uses environment variable
* `GRADLE_ENTERPRISE_API_MAX_CACHE_SIZE` or ~1 GB.
*/
var maxCacheSize =
System.getenv("GRADLE_ENTERPRISE_API_MAX_CACHE_SIZE")?.toLong()
?: 1_000_000_000L

/**
* Regex pattern to match API URLs that are OK to store long-term in the HTTP cache, up to
* [longTermCacheMaxAge] (1y by default, max value). By default, uses environment variable
* `GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_URL_PATTERN` or a pattern matching:
* - {host}/api/builds/{id}/gradle-attributes
* - {host}/api/builds/{id}/maven-attributes
*
* Gradle Enterprise API disallows HTTP caching, but this library forcefully removes such
* restriction.
*
* Use `|` to define multiple patterns in one, e.g. `.*gradle-attributes|.*test-distribution`.
*/
var longTermCacheUrlPattern: Regex =
System.getenv("GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_URL_PATTERN")?.toRegex()
?: """.*/api/builds/[\d\w]+/(?:gradle|maven)-attributes""".toRegex()

/**
* Max age in seconds for URLs to be cached long-term (matched by [longTermCacheUrlPattern]).
* By default, uses environment variable `GRADLE_ENTERPRISE_API_LONG_TERM_CACHE_MAX_AGE` or 1 year.
*/
var longTermCacheMaxAge: Long =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE")?.toLong()
?: 365.days.inWholeSeconds

/**
* Regex pattern to match API URLs that are OK to store short-term in the HTTP cache, up to
* [shortTermCacheMaxAge] (1d by default). By default, uses environment variable
* `GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_URL_PATTERN` or a pattern matching:
* - {host}/api/builds
*
* Gradle Enterprise API disallows HTTP caching, but this library forcefully removes such
* restriction.
*
* Use `|` to define multiple patterns in one, e.g. `.*gradle-attributes|.*test-distribution`.
*/
var shortTermCacheUrlPattern: Regex =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_URL_PATTERN")?.toRegex()
?: """.*/builds(?:\?.*|\Z)""".toRegex()

/**
* Max age in seconds for URLs to be cached short-term (matched by [shortTermCacheUrlPattern]).
* By default, uses environment variable `GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE` or 1 day.
*/
var shortTermCacheMaxAge: Long =
System.getenv("GRADLE_ENTERPRISE_API_SHORT_TERM_CACHE_MAX_AGE")?.toLong()
?: 1.days.inWholeSeconds

/**
* Enables debug logging from the library. All logging is output to stderr. By default, uses
* environment variable `GRADLE_ENTERPRISE_API_DEBUG_LOGGING` or `false`.
*/
var debugLoggingEnabled =
System.getenv("GRADLE_ENTERPRISE_API_DEBUG_LOGGING").toBoolean()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.gabrielfeo.gradle.enterprise.api.internal

import com.gabrielfeo.gradle.enterprise.api.debugLoggingEnabled
import com.gabrielfeo.gradle.enterprise.api.Options
import java.util.logging.Level.INFO
import java.util.logging.Logger

Expand All @@ -20,7 +20,7 @@ internal fun requireToken(

private fun tokenFromEnv(varName: String): String? {
return System.getenv(varName).also {
if (debugLoggingEnabled && it.isNullOrBlank()) {
if (Options.debugLoggingEnabled && it.isNullOrBlank()) {
Logger.getGlobal().log(INFO, "Env var $varName=$it")
}
}
Expand All @@ -36,7 +36,7 @@ private fun tokenFromKeychain(keyName: String): String? {
return process.inputStream.bufferedReader().use {
it.readText().trim()
}
} else if (debugLoggingEnabled) {
} else if (Options.debugLoggingEnabled) {
Logger.getGlobal().log(INFO, "Failed to get key from keychain (exit $status)")
}
return null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
package com.gabrielfeo.gradle.enterprise.api.internal

import com.gabrielfeo.gradle.enterprise.api.*
import com.gabrielfeo.gradle.enterprise.api.internal.auth.HttpBearerAuth
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheEnforcingInterceptor
import com.gabrielfeo.gradle.enterprise.api.internal.caching.CacheHitLoggingInterceptor
import com.gabrielfeo.gradle.enterprise.api.internal.caching.cache
import com.gabrielfeo.gradle.enterprise.api.accessToken
import com.gabrielfeo.gradle.enterprise.api.longTermCacheMaxAge
import com.gabrielfeo.gradle.enterprise.api.longTermCacheUrlPattern
import com.gabrielfeo.gradle.enterprise.api.maxConcurrentRequests
import com.gabrielfeo.gradle.enterprise.api.shortTermCacheMaxAge
import com.gabrielfeo.gradle.enterprise.api.shortTermCacheUrlPattern
import com.gabrielfeo.gradle.enterprise.api.internal.caching.buildCache
import okhttp3.OkHttpClient

internal val okHttpClient: OkHttpClient by lazy {
OkHttpClient.Builder()
.cache(cache)
.addInterceptor(HttpBearerAuth("bearer", accessToken()))
.cache(buildCache())
.addInterceptor(HttpBearerAuth("bearer", Options.accessToken()))
.addInterceptor(CacheHitLoggingInterceptor())
.addNetworkInterceptor(buildCacheEnforcingInterceptor())
.build()
.apply {
dispatcher.maxRequests = maxConcurrentRequests
dispatcher.maxRequestsPerHost = maxConcurrentRequests
dispatcher.maxRequests = Options.maxConcurrentRequests
dispatcher.maxRequestsPerHost = Options.maxConcurrentRequests
}
}

private fun buildCacheEnforcingInterceptor() = CacheEnforcingInterceptor(
longTermCacheUrlPattern = longTermCacheUrlPattern,
longTermCacheMaxAge = longTermCacheMaxAge,
shortTermCacheUrlPattern = shortTermCacheUrlPattern,
shortTermCacheMaxAge = shortTermCacheMaxAge,
longTermCacheUrlPattern = Options.longTermCacheUrlPattern,
longTermCacheMaxAge = Options.longTermCacheMaxAge,
shortTermCacheUrlPattern = Options.shortTermCacheUrlPattern,
shortTermCacheMaxAge = Options.shortTermCacheMaxAge,
)
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.gabrielfeo.gradle.enterprise.api.internal

import com.gabrielfeo.gradle.enterprise.api.baseUrl
import com.gabrielfeo.gradle.enterprise.api.Options
import com.gabrielfeo.gradle.enterprise.api.internal.infrastructure.Serializer
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory

internal val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(baseUrl())
.baseUrl(Options.baseUrl())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(Serializer.moshi))
.client(okHttpClient)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package com.gabrielfeo.gradle.enterprise.api.internal.caching

import com.gabrielfeo.gradle.enterprise.api.cacheDir
import com.gabrielfeo.gradle.enterprise.api.debugLoggingEnabled
import com.gabrielfeo.gradle.enterprise.api.maxCacheSize
import com.gabrielfeo.gradle.enterprise.api.Options
import okhttp3.Cache
import java.util.logging.Level.INFO
import java.util.logging.Logger

internal val cache: Cache = run {
if (debugLoggingEnabled) {
Logger.getGlobal().log(INFO, "HTTP cache dir with max size $maxCacheSize: $cacheDir")
internal fun buildCache(): Cache {
if (Options.debugLoggingEnabled) {
val logger = Logger.getGlobal()
logger.log(INFO, "HTTP cache dir: ${Options.cacheDir} (max ${Options.maxCacheSize}B)")
}
Cache(cacheDir, maxSize = maxCacheSize)
return Cache(Options.cacheDir, maxSize = Options.maxCacheSize)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.gabrielfeo.gradle.enterprise.api.internal.caching

import com.gabrielfeo.gradle.enterprise.api.debugLoggingEnabled
import com.gabrielfeo.gradle.enterprise.api.Options
import okhttp3.Interceptor
import okhttp3.Response
import java.util.logging.Level
Expand All @@ -11,7 +11,7 @@ internal class CacheHitLoggingInterceptor(
) : Interceptor {

override fun intercept(chain: Interceptor.Chain): Response {
if (!debugLoggingEnabled) {
if (!Options.debugLoggingEnabled) {
return chain.proceed(chain.request())
}
val url = chain.request().url
Expand Down

0 comments on commit 5905c5f

Please sign in to comment.