How to use Gradle remote cache with a custom logic to make a task NOT up-to-date?

Hi,

We are working on making compilation intelligent for OpenEdge ABL language by being able to identify any Database changes and marking the task as NOT up-to-date if there are any changes.
(The database connection and compilation are all specific to OpenEdge and there is already an existing plugin and task type to do the compilation.)

After researching Gradle documents, I came across this option called upToDateWhen(). The logic implemented is something like this,

  • The compile task (task type is ABLCompile), generates a JSON file, say, tooling.json, with info of the table references. (Basically, a map of tables and their CRC values, for example, say “Sports.Customer”: “12345”)
  • In the next task execution, the task has the input of Database connection details and it can verify if the CRC value has changed (for the tables used) by comparing the value present in the database server and this tooling.json file.
  • The tooling.json file is configured as an OutputFile so that it can make into Gradle’s remote cache

All of this works great until we run the compile task in a clean environment. The problem is that by the time this event, TaskOutputs.upToDateWhen(), is executed, the Gradle remote cache is not loaded, hence this tooling.json is not present and hence the check to identify database changes doesn’t happen as expected.

  • One workaround is to always run the compile task twice in a clean environment, but obviously, that is not something the first solution we prefer.
  • I also tried using a task, say, preCompileCheck, that can do the database change check but since that task also has to depend on this tooling.json (which is generated by the compile task itself), it creates a cyclic dependency and I ran into the similar problem of loading it in a clean environment.

So, here are my questions,

  1. Is there a better way of doing this, adding custom logic to make a task NOT up-to-date, where the custom logic is also dependent on the output of the task itself? Or, Is there something we can configure that can help us?
  2. Is there a way we can enforce the loading of the Gradle cache for the compile task, either before or as part of the TaskOutputs.upToDateWhen() execution?
  3. Is there a way to explicitly load the Gradle remote cache without running the task?

Let me know your thoughts/suggestions, it will greatly help us. At this point, we are out of ideas.

None I’m aware of for 2 and 3 and I would wonder if anything existed, especially in public API.

Why does the JSON have to be generated by the compile task? Obviously you can calculate the necessary information up-front as you do in your check. So how about indeed doing such a pre-compile “build database content JSON” task, that does not do any check, but just creates that file as output. And then you simply declare that task as input file for the compilation task. That was the file contents become input for the compile task and should achieve what you intend I think.

Alternatively, you could declare the compile task to not be cacheable. It can still be up to date, but will not be cached anymore. The cache is not for restoring “some” previous state and then maybe run the task, but the cache is to not run the task and simply take the previous result.

Thanks a lot for the response @Vampire.

This tooling JSON file is generated from the compiler’s metadata output (which has table references present in ABL source code). So that is why it is getting complicated and we are pursuing a good Gradle solution.

I don’t think marking the compile task to not be cacheable is an option because we want to leverage Gradle’s cache for faster builds (if there are no changes to the projects).
A related idea is to check-in the tooling JSON file and that should solve this, but developers will have to maintain this file, and this is prone to discrepancies compared to CI environments.

Are there any other suggestions?

For Q2 and Q3, does it make sense to have such a feature in Gradle or is there anything related in the backlog?

Sorry if I’m stubborn, but what you say does not make full sense to me.
In your “is it up-to-date check”, you calculate something and compare that something to something from that JSON file.
Why can you not calculate that something and store it to a file instead?
It does not have to be JSON or that JSON the compiler generates.
It just have to be the information you would compare, so that the task can see “the file is the same” or “the file is different”.

For Q2 and Q3, does it make sense to have such a feature in Gradle

If you ask me, probably not.
But feel free to open a feature request and see what the Gradle folks say.
I’m just a user like you.

or is there anything related in the backlog?

Search through the GitHub issues, that’s also all information I have.
If it is in some non-public backlog, I wouldn’t know either.