This message was deleted.
# configuration-cache
s
This message was deleted.
v
Probably, yeah, as the
onlyIf
is checked at execution time.
m
I confirm :) The notion of execution time was a bit imprecise with regard to the getProject check before 8.1. It is now fixed, so there's a CC problem emitted, and not a silently incorrect build.
šŸ‘Œ 1
thank you 1
e
In that case then I'm guessing that the following line in the
onlyIf
is the culprit here:
Copy code
project.gradle.taskGraph.allTasks.any { it.state.failure != null }
Is there an easy way to make that work with the CC? I'm not really familiar with this project and it is no longer maintained, so I'm looking for a quick and easy fix if possible šŸ˜…
v
Record the task state in an
OperationCompletionListener
and check that instead of the taskgraph?
g
Are you working on fixing that @Eli Graber? I've been working in that the whole day today, managed to some progress, but based on my tests
onlyIf
closures are now evaluated at configuration time and not at execution time, I am right? Maybe not configuration time, but definitely before the dependent tasks are run šŸ¤”
@Vampire can you elaborate a bit how the
OperationCompletionListener
would work? Basically what we need to archive is to run a
finalizedBy
task but only if the dependent where successful. The original logic was accessing the taskgraph to gather their result, but now this is a violation of CC. I've tried moving the logic to a
Provider<Boolean>
but tests are not passing (only with CC enabled) because the behavior is different, the provider gets evaluated before the tasks are run cc: @Zac Sweers
v
You mean
a.finalizedBy(b)
but
b
should only run if
a
was successful?
Copy code
a.finalizedBy(b)
b.dependsOn(a)
No custom trickery needed.
g
Yes, but, the logic on
CommitEdit
is a bit hacky. It should commit the Play Store transaction if the dependents tasks where successful. But it should rollback (by calling
apiService.get().cleanup()
if they weren't).
The
cleanup
was done before as part of the
onlyIf
spec (not ideal) but now the
onlyIf
is evaluated at configuration phase, I'm wondering if that's an issue šŸ¤” as the docs says it's evaluated just before the task is run
I was think that the right behavior will be to split the task in two: one for commit, and another for rollback
v
I don't believe that without proof. šŸ˜„
g
You mean
a.finalizedBy(b)
but
b
should only run if
a
was successful?
Both, we need to change the behavior based on the outcome of previous tasks
v
Yeah, then have a build service that you register as operation completion listener where you record the outcome of the previous task and then use the build service's value to decide whether to commence or cleanup
g
I don't believe that without proof.
I put a breakpoint in the provider, look at the terminal, it's evaluated at
100% CONFIGURING
(when it's stored to cache) and without CC, it's evaluated just before the task is about to run, but after the other had run šŸ¤”
v
And what do you do with that provider? Because here the counterproof:
Copy code
tasks.configureEach {
    onlyIf {
        println("onlyIf for $name")
        true
    }
    doFirst {
        println("execution of $name")
    }
}
Copy code
$ gw --configuration-cache build
Encryption of the configuration cache is enabled.
Reusing configuration cache.

> Task :processResources UP-TO-DATE
onlyIf for processResources

> Task :processTestResources UP-TO-DATE
onlyIf for processTestResources

> Task :compileJava UP-TO-DATE
onlyIf for compileJava

> Task :classes
onlyIf for classes
execution of classes

> Task :jar UP-TO-DATE
onlyIf for jar

> Task :assemble
onlyIf for assemble
execution of assemble

> Task :compileTestJava UP-TO-DATE
onlyIf for compileTestJava

> Task :testClasses
onlyIf for testClasses
execution of testClasses

> Task :test UP-TO-DATE
onlyIf for test

> Task :check
onlyIf for check
execution of check

> Task :build
onlyIf for build
execution of build

BUILD SUCCESSFUL in 17s
11 actionable tasks: 5 executed, 6 up-to-date
Configuration cache entry reused.
šŸ¤” 1
g
Not 100% sure right now, as I jump in into the project because we use this plugin as part of the CI. The full code is here but basically, it's
.get
is called as part of the
onlyIf
closure, added in a
init
method of the same task. The task is registered in the graph with
finalizeBy
by other tasks.
Well, I managed to reproduce it with a minimum example:
Copy code
val finalTask by tasks.registering {
    val prov = provider { project.gradle.taskGraph.allTasks.any { println("*** provider called: ${it.path}"); true } }
    onlyIf { prov.get() }
    doFirst { println("*** finalTask run") }
}

val someTask by tasks.registering {
    finalizedBy(finalTask)
    doFirst { println("*** someTask run") }
}
./gradlew aaa
shows:
Copy code
āÆ ./gradlew someTask

> Task :app:someTask
*** someTask run

> Task :app:finalTask
*** provider called: :app:someTask
*** finalTask run
and
./gradlew aaa --configuration-cache
shows:
Copy code
āÆ ./gradlew someTask --configuration-cache
Encryption of the configuration cache is enabled.
Calculating task graph as no configuration cache is available for tasks: someTask
*** provider called: :app:someTask

> Task :app:someTask
*** someTask run

> Task :app:finalTask
*** finalTask run
Gradle version is
8.1.1
. Should I fill a bug? or this is expected?
v
In that example the
prov
is probably state on the task and thus on serialization queried and persisted
So I guess in that MCVE it is like expected, but I'm not 100% sure
šŸ‘€ 1
g
FYI, I finally make it work by introducing
AutoCloseable
(to rollback) and
OperationCompletionListener
(to know if any previous task has failed) in the
PlayApiService
. Thanks a lot @Vampire for the hints!
onlyIf
is evaluated at configuration phase,
I think the behavior is "any provider created while a task is configuring" is resolved at configuration time and stored into the cache. It would be nice to have some official word/doc regarding this to confirm it. But definitely, it behaves in a different way when CC is on.
v
I think the behavior is "any provider created while a task is configuring" is resolved at configuration time
No, the tasks state is serialized to CC. Providers are resolved at serialization time and their result serialized to CC. The
onlyIf
closure is part of the task and things it references are thus automatically also such state. In your case you reference the
prov
within
onlyIf
, so
prov
gets serialized, so that the
onlyIf
can access its value at execution time. And as
prov
is a provider, it is resolved at CC store time. If you add to your MCVE a
println("*** onlyIf called")
within the
onlyIf
you see that the
onlyIf
is indeed run at execution time. Just the provider is realized at CC store time.
thank you 1
āœ… 1
FYI, I finally make it work by introducing
AutoCloseable
(to rollback) and
OperationCompletionListener
(to know if any previous task has failed) in the
PlayApiService
.
If you do the rollback in the build service, you could also do the commit in the build service. Or if you want to keep the split, you could actually leave out the
onlyIf
check then and do what I initialliy suggested, adding an additional
dependsOn
, so that the finalizer task is only run on success.
g
dependsOn
, so that the finalizer task is only run on success.
That won't work as we have may "potential" tasks getting registerer/created. Adding
dependsOn
(to archive "only on success") will force all of them to run, just because one of team has run. I'm wondering if we need an API to complement
finalizedBy
to know about the outcome of its previous tasks šŸ¤” Clarifing, the plugin adds: • publishApk • publishBundle • publishStoreDetails (or similar, don't remember exactly) • etc, etc All of them are followed by
commitEdit
with
finalizedBy
but only if didn't fail. Adding the oposite
dependsOn
will force all of them to run. I couldn't find a way to archive the behavior with the current API, so I'm taking tracking their outcome in the
BuildService
and the
commitEdit
check if any has file as a
onlyIf
condition.
v
Ah, yeah, important detail you left out. šŸ˜„ Then, yes, the build service as operation completion listener that provides the relevant outcome is the way to go.
šŸ’Ŗ 3
šŸ˜… 1