Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: check if daemon actually running #315

Closed
wants to merge 5 commits into from

Conversation

L2jLiga
Copy link
Contributor

@L2jLiga L2jLiga commented Sep 19, 2024

Implemented new command - ESLINT_D_PING to check whether daemon is actually running or not. This gives us ability to check daemon and start it if required before sending user command to it.

Implemented new command - ESLINT_D_PING to check whether daemon
is actually running or not. This gives us ability to check
daemon and start it if required before sending user command to it.
Copy link
Owner

@mantoni mantoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This is a very useful stability enhancement. I have some comments about how it's implemented.

lib/forwarder.js Outdated Show resolved Hide resolved
lib/service.js Outdated Show resolved Hide resolved
lib/service.test.js Outdated Show resolved Hide resolved
bin/eslint_d.js Outdated
@@ -54,7 +60,7 @@ const command = process.argv[2];
(await import('../lib/status.js')).status(resolver, config);
return;
default:
if (config && config.hash !== hash) {
if (config && (config.hash !== hash || !(await isAlive(config)))) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using isAlive in the start and status commands is a very good improvement. But calling it here adds an extra roundtrip to the server on every lint call. I ran some quick tests and it slows it down quite a bit. Given that this is the hot code execution path, I'd like to not do that here.

There is a good alternative though: The forwardToDaemon function already handles connection errors and removes the config. Instead of doing that in the function itself, forwardToDaemon could return a flag or throw an exception, so that this file here could handle connection issues, restart the service and try sending the request again. This would eliminate the need to call isAlive with the same behaviour.

Am I missing something? What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, I think using optimistic approach is good idea at least because this check will return "true" most of the time

removed JSON payload from PING command
lib/forwarder.js Outdated Show resolved Hide resolved
lib/service.js Outdated Show resolved Hide resolved
lib/service.test.js Outdated Show resolved Hide resolved
lib/service.test.js Show resolved Hide resolved
lib/forwarder.js Outdated Show resolved Hide resolved
lib/launcher.js Outdated Show resolved Hide resolved
lib/service.js Outdated Show resolved Hide resolved
@L2jLiga L2jLiga marked this pull request as draft September 23, 2024 23:20
@L2jLiga
Copy link
Contributor Author

L2jLiga commented Sep 23, 2024

Convert to draft because have to investigate why there's abandoned connections

lib/forwarder.js Outdated
const socket = await connectToDaemon(config);
socket.write(JSON.stringify([config.token, command]));
if (command === SHUTDOWN_COMMAND) {
socket.destroySoon();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea why destroySoon is needed, but without this method call daemon will never stop

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Maybe because we're calling shutdown() immediately which closes the server, and then we're calling .end() on the socket? Just a wild guess ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as far as I understand this is related to server.close and half-open connections, for some reasons this connections could not be closed if server is closing, so I've implemented logic to await for connections completion, seems to work fine

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I've fixed all tests that was trivial to fix, 3 tests still failing, if you're ok with solution I'll continue fixing this tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After all tests are fixed I will continue with restart daemon logic in forwardToDaemon function

try {
socket = await connectToDaemon(config);
} catch (/** @type {any} */ err) {
if (err['code'] === 'ECONNREFUSED') {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 99% cases this is the only reason promise rejects, also here we didn't sent any data to socket yet, already read stdin and didn't write anything to connection, I think it's good place to integrate restart logic

})
);

waitForConnections()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure you're trying to work around some other issue here. server.close() actually waits for any pending connections and doesn't invoke the callback until all connections are gone.

See https://nodejs.org/api/net.html#serverclosecallback.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right, finally I've found root cause:
the issue was with waitForConfig, for the moment when it was called in stopDaemon - it was already removed, so watcher never get notification about

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's correct fix:
#316

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After #316 merged gonna rebase and cleanup things if you don't mind, otherwise can start new PR

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged. Thank you!

@L2jLiga
Copy link
Contributor Author

L2jLiga commented Sep 26, 2024

Superseded by #316 and #317

@L2jLiga L2jLiga closed this Sep 26, 2024
@L2jLiga L2jLiga deleted the feature/is-alive branch September 26, 2024 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants