This message was deleted.
# community-support
s
This message was deleted.
s
Currently, the issue is that I am using
project
inside of it for various cases, and it seems like the error message tells me that I can not use that at all. At first, I was using project.file it to get a hold of some temporary file to download something into, which it gets deleted at the end of this task. For this, a replacement seems to be
public File getTemporaryDir()
which exists inside
DefaultTask
so using that it seems like it’s all okay now But then, we’re also using the
project
object in order to both: 1) Get access to the copy action in order to take that downloaded zip and paste it into a provided directory. 2) Get the
zipTree
function which helps us deal with that downloaded zip file to pass into the
from
function of that copy task. For the copy task, maybe the Worker API is what I am looking for, as I see a nice example there of getting FileSystemOperations injected into it, so that we can get the
copy
function and use it using this worked, so I will look into that. But I couldn’t find some documentation about the zipTree fuction, and trying to also inject
FileOperations
seems to fail, it only knows how to inject
FileSystemOperators
, with error “Unable to determine constructor argument #2: missing parameter of type FileOperations, or no service of type FileOperations.” Any ideas if I am going down the right path, and if there’s some documentation I am missing for this?
a
for
copy {}
you can inject
FileSystemOperations
, and for
zipTree {}
there’s
ArchiveOperations
https://docs.gradle.org/current/userguide/custom_gradle_types.html#service_injection
t
a
replace
Copy code
abstract class DownloadStringsTask : DefaultTask() {
with
Copy code
import javax.inject.Inject

abstract class DownloadStringsTask @Inject constructor(
  private val fs: FileSystemOperations,
  private val archives: ArchiveOperations,
): DefaultTask() {
👍 1
It’s fine to use the
tempraryDir
as you have, but it might be a good idea to register it as a
@LocalState
Copy code
@get:LocalState
val cacheDir: File get() = temporaryDir
https://docs.gradle.org/current/userguide/custom_tasks.html#sec:storing_incremental_task_state
s
Oh okay, and this just works, no need to even use the Worker API. Damn, y’all are life savers, I can’t thank you enough! In order to teach myself to fish as well, instead of just giving me the fish, where in the docs is this ArchiveOperations decsribed? I really couldn’t find it. I am sure it’s because I didn’t know how to properly search for it, but still
👍 1
a
I always google
gradle inject services
to find the services
thank you 1
s
The reason I am using the file here is to store something locally as a download target, then use that file to fetch the content, unzip it and then delete it completely, it’s never supposed to exist before or after the task is done. This @LocalState seems to be used for when state is also persistent across runs no?
a
as I understand it, that’s basically the point. Gradle will delete LocalState if it ever realises it needs to clear the cache.
thank you 1
s
Hmm no maybe I misunderstood. Reading the javadoc above it it seems like I want to use it 😊
Again, thanks so much! You both really came in clutch here 🤗
a
no problem! Happy to help. Keep the questions coming!
party gradlephant 1
s
That was easy afterall 😅 If someone in the future bumps into this thread, here’s how all this looked like as a PR to our repo. https://github.com/HedvigInsurance/android/pull/1555. Hope this helps someone.
🚀 1
v
@LocalState
should not be necessary though for two reasons. • the task does not reuse the state in that file, it just overwrites the file if the task is rerun • the task is not cacheable
👍 1
"local state" means, that if the task output is taken from the build cache, then this state is deleted, as it is local state of some tool that can work incrementally if that local state matches the output
In the given case, this is just useless 🙂
s
Right, thanks a lot for clearing that up. Yeah in my case I’ll just remove it then! With this said, can I also omit doing
temporaryCacheDir.delete()
now then? Since I’ll just use
temporaryDir
directly. I am assuming this temporaryDir is something that gets auto-deleted at the the of the task run right? I tried locating where it’s created while the task is still running to ensure that this is the case but didn’t find a way to do so this far.
v
Actually it is not a "real" temporary dir. It is not auto-deleted at any time. If you want to clear it out at the beginning or end of your task, you need to do it yourself. Otherwise you could also just use a regular JVM temporary directory, that then is cleared out by the operating system.
s
Alright, seems like I do want to do temporaryDir.delete() at the end of the task then. I don't find a reason to keep those files around. Is this directory shared potentially with other tasks? If yes I maybe should proactively delete the contents before the task starts too.
v
No
Each task has its own temp dir
👍 1
a
the
temporaryDir
for each task is
./build/tmp/nameOfTask
. So it’s not shared with other tasks. I wouldn’t worry about overlapping - Gradle will warn if there’s two tasks are clashing
v
But it shouldn't hurt to delete in the beginning, maybe your task fail last time before getting to the deletion
👍 2
So clean in the end to clean up, clean in the beginning to have a clear plate
Or, as I said, just use the normal Java temporary directory.
That task-specific temp directory, is actually more useful for things like local state that you don't have here and that is reused across task executions somehow.
s
Yes, I see what you mean. And by temporary java directory, I’m assuming you mean
File.createTempFile("lang-file", ".zip")
in my case. Just tested this too and it also just works it seems. Might as well let it be like this then. And this should actually get auto-cleared. Doesn’t seem like this is automatic, actually 😅 Anyway, maybe I shouldn’t overthink this, it’s okay regardless.
👌 1
v
Whethter it is auto-cleaned depends on your OS. Linux e.g. will clean it on restart.
Windows will clean it if you are running out of space and manually tell it to clean up things
But you can of course still delete the file at the end of the task or as soon as it is not needed anymore.
👍 1
s
Yeah, this is the best all around solution I think too. Delete in the OK case. If my task crashes and the file stays around, not a big deal as it should be deleted eventually anyway (I am on MacOS atm)
a
there is
File.deleteOnExit()
https://stackoverflow.com/questions/19012557/use-of-deleteonexit-method-in-java, but I agree that you shouldn’t overthink it :) Using
createTempFile()
will be fine, unless the file is sensitive, but then nothing about this is sensitive, so there are bigger problems
👍 1
v
But be careful with
deleteOnExit
. It is fine for things that currently cannot be deleted because somehow the file is still in use or similar but can maybe be deleted later and if not, then not. But those actions are not guaranteed to be run just like JVM shutdown hooks iirc.
Yes, it actually is implemented as a shutdown hook, so has the same problems / uncertainties
e
deleteOnExit()
isn't very timely in the long-lived Gradle daemon anyway
👍 2
v
That too, yes. Try to delete, if failed try to delete at JVM exit, if not run or still not possible, corpse.
👍 1