A ValueSource can take parameters in the form of Properties. A BuildService is obtained as a Provider. This Provider can be wired to the input Property of the ValueSource. It works well without the configuration cache. However, when the configuration cache is enabled and the ValueSource is obtained at the configuration time, things go wrong. The cache cannot be reused, as the fingerprinting routine cannot restore the BuildService; the build fails with a cryptic exception.
Expected Behavior
Either of two options are expected:
- If Gradle is not going to support this use case: provide an error with a clear message that this use is unsupported, preferably when storing the cache
- Otherwise, this should just work, and the service instance should be available for the ValueSource computation.
Current Behavior
The build fails when trying to check the cache validity:
org.gradle.api.GradleException: Could not load the value of field `__service__` of `ServiceValueSource$Params` bean found in field `parameters` of `org.gradle.api.internal.provider.DefaultValueSourceProviderFactory$DefaultObtainedValue` bean found in field `obtainedValue` of `org.gradle.configurationcache.fingerprint.ConfigurationCacheFingerprint$ValueSource` bean found in Gradle runtime.
at org.gradle.configurationcache.serialization.beans.BeanPropertyReaderKt.readPropertyValue(BeanPropertyReader.kt:108)
at org.gradle.configurationcache.serialization.beans.BeanPropertyReader.readStateOf(BeanPropertyReader.kt:67)
at org.gradle.configurationcache.serialization.codecs.BeanCodec.readBeanOf(BeanCodec.kt:72)
at org.gradle.configurationcache.serialization.codecs.BeanCodec.decode(BeanCodec.kt:47)
at org.gradle.configurationcache.serialization.CombinatorsKt$reentrant$1$decodeLoop$1.invokeSuspend(Combinators.kt:165)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlin.coroutines.ContinuationKt.startCoroutine(Continuation.kt:115)
at org.gradle.configurationcache.serialization.CombinatorsKt$reentrant$1.decodeLoop(Combinators.kt:166)
at org.gradle.configurationcache.serialization.CombinatorsKt$reentrant$1.decode(Combinators.kt:130)
at org.gradle.configurationcache.serialization.codecs.BindingsBackedCodec.decode(BindingsBackedCodec.kt:59)
at org.gradle.configurationcache.serialization.DefaultReadContext.read(Contexts.kt:259)
at org.gradle.configurationcache.fingerprint.ConfigurationCacheFingerprintChecker.checkBuildScopedFingerprint(ConfigurationCacheFingerprintChecker.kt:58)
at org.gradle.configurationcache.fingerprint.ConfigurationCacheFingerprintController.checkBuildScopedFingerprint(ConfigurationCacheFingerprintController.kt:243)
at org.gradle.configurationcache.DefaultConfigurationCache$checkBuildScopedFingerprint$1.invokeSuspend(DefaultConfigurationCache.kt:461)
at org.gradle.configurationcache.DefaultConfigurationCache$readFingerprintFile$1$1.invokeSuspend(DefaultConfigurationCache.kt:480)
at org.gradle.configurationcache.ConfigurationCacheIO$withReadContextFor$1$1$1$1.invokeSuspend(ConfigurationCacheIO.kt:248)
at org.gradle.configurationcache.serialization.RunningKt$runReadOperation$2.invokeSuspend(Running.kt:34)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlin.coroutines.ContinuationKt.startCoroutine(Continuation.kt:115)
at org.gradle.configurationcache.serialization.RunningKt.runToCompletion(Running.kt:56)
at org.gradle.configurationcache.serialization.RunningKt.runReadOperation(Running.kt:33)
at org.gradle.configurationcache.ConfigurationCacheIO.withReadContextFor$configuration_cache(ConfigurationCacheIO.kt:247)
at org.gradle.configurationcache.DefaultConfigurationCache.readFingerprintFile(DefaultConfigurationCache.kt:478)
at org.gradle.configurationcache.DefaultConfigurationCache.checkBuildScopedFingerprint(DefaultConfigurationCache.kt:459)
at org.gradle.configurationcache.DefaultConfigurationCache.checkFingerprintAgainstLoadedProperties(DefaultConfigurationCache.kt:441)
at org.gradle.configurationcache.DefaultConfigurationCache.checkFingerprint(DefaultConfigurationCache.kt:429)
at org.gradle.configurationcache.DefaultConfigurationCache.access$checkFingerprint(DefaultConfigurationCache.kt:53)
at org.gradle.configurationcache.DefaultConfigurationCache$checkFingerprint$1.invoke(DefaultConfigurationCache.kt:278)
at org.gradle.configurationcache.DefaultConfigurationCache$checkFingerprint$1.invoke(DefaultConfigurationCache.kt:271)
at org.gradle.configurationcache.ConfigurationCacheRepository$StoreImpl$useForStateLoad$2.invoke(ConfigurationCacheRepository.kt:164)
at org.gradle.configurationcache.ConfigurationCacheRepository$StoreImpl$useForStateLoad$2.invoke(ConfigurationCacheRepository.kt:163)
at org.gradle.configurationcache.ConfigurationCacheRepository$withExclusiveAccessToCache$1.create(ConfigurationCacheRepository.kt:244)
at org.gradle.cache.internal.LockOnDemandCrossProcessCacheAccess.withFileLock(LockOnDemandCrossProcessCacheAccess.java:90)
at org.gradle.cache.internal.DefaultCacheAccess.withFileLock(DefaultCacheAccess.java:191)
at org.gradle.cache.internal.DefaultPersistentDirectoryStore.withFileLock(DefaultPersistentDirectoryStore.java:188)
at org.gradle.cache.internal.DefaultCacheFactory$ReferenceTrackingCache.withFileLock(DefaultCacheFactory.java:209)
at org.gradle.configurationcache.ConfigurationCacheRepository.withExclusiveAccessToCache(ConfigurationCacheRepository.kt:242)
at org.gradle.configurationcache.ConfigurationCacheRepository.access$withExclusiveAccessToCache(ConfigurationCacheRepository.kt:46)
at org.gradle.configurationcache.ConfigurationCacheRepository$StoreImpl.useForStateLoad(ConfigurationCacheRepository.kt:163)
at org.gradle.configurationcache.DefaultConfigurationCache.checkFingerprint(DefaultConfigurationCache.kt:271)
at org.gradle.configurationcache.DefaultConfigurationCache.determineCacheAction(DefaultConfigurationCache.kt:221)
at org.gradle.configurationcache.DefaultConfigurationCache.initializeCacheEntry(DefaultConfigurationCache.kt:114)
at org.gradle.configurationcache.ConfigurationCacheBuildTreeLifecycleControllerFactory.createRootBuildController(ConfigurationCacheBuildTreeLifecycleControllerFactory.kt:54)
at org.gradle.composite.internal.DefaultRootBuildState.<init>(DefaultRootBuildState.java:73)
at org.gradle.composite.internal.BuildStateFactory.createRootBuild(BuildStateFactory.java:66)
at org.gradle.composite.internal.DefaultIncludedBuildRegistry.createRootBuild(DefaultIncludedBuildRegistry.java:91)
...
Caused by: java.lang.IllegalArgumentException: Could not find build ':'
at org.gradle.composite.internal.DefaultIncludedBuildRegistry.getBuild(DefaultIncludedBuildRegistry.java:147)
at org.gradle.configurationcache.serialization.codecs.BuildServiceProviderCodec.buildServiceRegistryOf(ProviderCodecs.kt:188)
at org.gradle.configurationcache.serialization.codecs.BuildServiceProviderCodec.decode(ProviderCodecs.kt:183)
at org.gradle.configurationcache.serialization.codecs.BindingsBackedCodec.decode(BindingsBackedCodec.kt:59)
at org.gradle.configurationcache.serialization.codecs.FixedValueReplacingProviderCodec.decodeValue(ProviderCodecs.kt:134)
at org.gradle.configurationcache.serialization.codecs.FixedValueReplacingProviderCodec.decodeProvider(ProviderCodecs.kt:116)
at org.gradle.configurationcache.serialization.codecs.PropertyCodec.decode(ProviderCodecs.kt:269)
at org.gradle.configurationcache.serialization.codecs.BindingsBackedCodec.decode(BindingsBackedCodec.kt:59)
at org.gradle.configurationcache.serialization.DefaultReadContext.read(Contexts.kt:259)
at org.gradle.configurationcache.serialization.beans.BeanPropertyReaderKt.readPropertyValue(BeanPropertyReader.kt:102)
Context
My goal was to invalidate the configuration cache with the value obtained through the BuildService (with a side effect): the service is starting a web server on a random port, the URL of the server is used to configure some tasks. The build service then stops the server when closed.
The use case is not very compelling, as the lifecycle of the service is unclear in case the cache is actually invalidated - is the service used at fingerprint check time going to be discarded?
Steps to Reproduce
See #22338.
A
ValueSourcecan take parameters in the form of Properties. ABuildServiceis obtained as aProvider. ThisProvidercan be wired to the inputPropertyof the ValueSource. It works well without the configuration cache. However, when the configuration cache is enabled and the ValueSource is obtained at the configuration time, things go wrong. The cache cannot be reused, as the fingerprinting routine cannot restore theBuildService; the build fails with a cryptic exception.Expected Behavior
Either of two options are expected:
Current Behavior
The build fails when trying to check the cache validity:
Context
My goal was to invalidate the configuration cache with the value obtained through the BuildService (with a side effect): the service is starting a web server on a random port, the URL of the server is used to configure some tasks. The build service then stops the server when closed.
The use case is not very compelling, as the lifecycle of the service is unclear in case the cache is actually invalidated - is the service used at fingerprint check time going to be discarded?
Steps to Reproduce
See #22338.