Description
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
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
- 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.