You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have multiple prettier-based tasks in our project, and we occasionally observe java.net.ConnectException: connection denied. This only happens in subprojects where multiple file types need to be formatted and use the same npm packages.
I’m not sure about the root cause, but I have a theory: NpmFormatterStepStateBase#npmRunServer has a race condition that would cause the behaviour we’re seeing.
The method works as follows:
Check the server.port file in the installation directory, delete it if it exists.
Start the Node.JS server.
Wait for the server.port file to exist.
Check the connection to the server using the port from server.port.
Crucially, two prettier tasks that use the same npm modules will share the installation directory. So we get the following race condition. I’ll explain using the example of a spotlessJson and a spotlessYaml task:
spotlessJson and spotlessYaml start (approximately) simultaneously.
spotlessJson and spotlessYaml pass the server.port file check before the other has started the server.
spotlessJson and spotlessYaml start the NPM server.
spotlessJson’s (for example) server starts first and creates server.port
One of the two tasks sees the server.port, uses the server to format their files, and shuts down the server.
The other task sees the server.port, tries to use the server, but can’t because the server has already shut down (it may even succeed in formatting some files).
@nedtwigg what do you think? Does this race condition exist or did I overlook something?
I’d consider contributing a fix if we agree that this is a likely root cause.
The text was updated successfully, but these errors were encountered:
We applied this workaround, which seems to fix the issue for us. It restricts Gradle to execute only one prettier-based spotless task in parallel per project. This workaround is consistent with the theory about the race condition:
val spotlessNpmService =
gradle.sharedServices.registerIfAbsent("spotlessNpm-"+ project.path, SpotlessNpmService::class) {
maxParallelUsages =1
}
afterEvaluate {
// we must do this in afterEvaluate because before that, the SpotlessExtension will not have// configured the task yet.
tasks.withType<SpotlessTask>().configureEach {
if (stepsInternalRoundtrip.steps.any { it.name =="prettier-format" }) {
usesService(spotlessNpmService)
}
}
}
jGleitz
changed the title
Connection Denied if Multiple NPM Tasks is the Same Modules
Connection Denied when Running Multiple NPM Tasks in the Same Project
Feb 19, 2025
We have multiple prettier-based tasks in our project, and we occasionally observe
java.net.ConnectException: connection denied
. This only happens in subprojects where multiple file types need to be formatted and use the same npm packages.I’m not sure about the root cause, but I have a theory:
NpmFormatterStepStateBase#npmRunServer
has a race condition that would cause the behaviour we’re seeing.The method works as follows:
server.port
file in the installation directory, delete it if it exists.server.port
file to exist.server.port
.Crucially, two
prettier
tasks that use the same npm modules will share the installation directory. So we get the following race condition. I’ll explain using the example of aspotlessJson
and aspotlessYaml
task:spotlessJson
andspotlessYaml
start (approximately) simultaneously.spotlessJson
andspotlessYaml
pass theserver.port
file check before the other has started the server.spotlessJson
andspotlessYaml
start the NPM server.spotlessJson
’s (for example) server starts first and createsserver.port
server.port
, uses the server to format their files, and shuts down the server.server.port
, tries to use the server, but can’t because the server has already shut down (it may even succeed in formatting some files).@nedtwigg what do you think? Does this race condition exist or did I overlook something?
I’d consider contributing a fix if we agree that this is a likely root cause.
The text was updated successfully, but these errors were encountered: