-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
watch should debounce the restart #51954
Comments
watch mode is already debounced: node/lib/internal/main/watch_mode.js Line 47 in b34512e
|
Indeed, but that node/lib/internal/watch_mode/files_watcher.js Lines 76 to 89 in bf4a63e
Try starting a project in
You will notice the following output from I believe the solution would be to debounce the calls to node/lib/internal/main/watch_mode.js Lines 120 to 122 in b34512e
|
@matthieusieben what do you think about such a solution? main...MoLow:watch-mode-global-debounce diff --git a/lib/internal/watch_mode/files_watcher.js b/lib/internal/watch_mode/files_watcher.js
index bbc13e67cc..02c836e14a 100644
--- a/lib/internal/watch_mode/files_watcher.js
+++ b/lib/internal/watch_mode/files_watcher.js
@@ -6,6 +6,7 @@ const {
SafeMap,
SafeSet,
StringPrototypeStartsWith,
+ Symbol,
} = primordials;
const { validateNumber, validateOneOf } = require('internal/validators');
@@ -21,6 +22,7 @@ const { setTimeout } = require('timers');
const supportsRecursiveWatching = process.platform === 'win32' ||
process.platform === 'darwin';
+const kGlobalDebounce = Symbol('kGlobalDebounce');
class FilesWatcher extends EventEmitter {
#watchers = new SafeMap();
#filteredFiles = new SafeSet();
@@ -74,16 +76,17 @@ class FilesWatcher extends EventEmitter {
}
#onChange(trigger) {
- if (this.#debouncing.has(trigger)) {
+ if (this.#debouncing.has(trigger) || this.#debouncing.has(kGlobalDebounce)) {
return;
}
if (this.#mode === 'filter' && !this.#filteredFiles.has(trigger)) {
return;
}
- this.#debouncing.add(trigger);
+ this.#debouncing.add(trigger).add(kGlobalDebounce);
const owners = this.#depencencyOwners.get(trigger);
setTimeout(() => {
this.#debouncing.delete(trigger);
+ this.#debouncing.delete(kGlobalDebounce);
this.emit('changed', { owners });
}, this.#debounce).unref();
} |
Hey @MoLow, I think that solution looks much simpler. It does change the way the class works though. An event will no longer be emitter for every individual change, which will break other current uses of that class. |
What about something like this then ? |
Recap of the things i tried:
#51986 suffers the same issue as |
how do you measure "to many" restarts? |
Consider the following:
Steps 9 to 12 are un-necessary and should be "swallowed" when the app started again in step 7. |
My suggestion is to keep:
|
thanks for this explanation, it helped me better understand the problem. this is what I have done in #51992 |
#51992 is clearly the right way of fixing un-necessary restarts. Any other solution I suggested is either too complex or adds event loop ticks that might cause more restarts than required. I thing you should keep your PR. There is still an issue with debouncing though. It acts more like a trickle than and actual debounce (if you update the same file faster than every 200ms, the |
What is the problem this feature will solve?
When watching the result of a build, and a build is triggered,
node --watch
will take a long time to actually restart. This is very likely due to the fact that it will trigger a restart for every single file that is changed.What is the feature you are proposing to solve the problem?
Waiting a (small) amount of time to allow more changes to occur before actually stopping & re-starting would make this feature much smoother when running in dev mode.
What alternatives have you considered?
Status quo implies that the restart is slow, even when small changes are made, depending on the build system.
For example, when working on a large
tsc --watch
, typescript will output a new file for any edited files, as well as all of its dependent. In this setup (or when the dev triggers a new full build of is ts project), node (in watch mode) take quite long to actually restart, due to the overhead of starting & stopping for every file that changes.The text was updated successfully, but these errors were encountered: