Actual behavior/steps to reproduce (the bug)
JavalinVue.rootDirectory("/vue", Location.EXTERNAL)
(have a large number of .vue files in /vue folder)
Run something that produces a lot of requests, e.g. scenario tests
Produces java.nio.file.FileSystemException: [...]/src/main/resources/vue: Too many open files exception
https://gist.github.com/jorunfa/4278f4d0c231d7b54d3348464689d94d
I'll try to investigate the issue myself.
It seems to happen if I run the scenario tests sequentially too, not just when running them in parallell, it just takes longer time. So maybe either files are not being closed as they should be, or the amount of files just makes it so that requests are opening files faster than it's able to close them.
In the last days I saw something in the code base.
fun Path.readText(): String {
val s = Scanner(Files.newInputStream(this), "UTF-8").useDelimiter("\\A")
return if (s.hasNext()) s.next() else ""
}
The scanner is never closed, could this be the problem? What about Files.readAllBytes()?
I think you're completely right.
fun Path.readText(): String = Files.readAllBytes(this).toString(charset("UTF-8"))
Seems to have done the trick.
Could also add .also { s.close() } to the current code:
fun Path.readText(): String {
val s = Scanner(Files.newInputStream(this), "UTF-8").useDelimiter("\\A")
return (if (s.hasNext()) s.next() else "").also { s.close() }
}
I'm not really against using Files.readAllBytes(this).toString(charset("UTF-8")), I'm just wondering if it will behave the same in all the different environments, so closing the scanner seems safer.
readAllBytes seems to work fine in distroless Java container (which was where we had a problem before).
I have very little experience with the Scanner class, so I'm not sure, but it seems like one of its primary purposes is scanning for input, i.e. from user input through System.in, but of course other sources are also possible. E.g.:
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
We always read the full .vue file. readAllBytes makes sense to me. Not my area of expertise though.
Most helpful comment
In the last days I saw something in the code base.
The scanner is never closed, could this be the problem? What about
Files.readAllBytes()?