Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

Fix: watch local modules other bundles #1370

Closed
wants to merge 13 commits into from

Conversation

PixnBits
Copy link
Contributor

@PixnBits PixnBits commented Apr 5, 2024

Description

During development use filesystem polling to detect modules being built and then reload them in the running server. This increases the filesystem and CPU usage, but is much more reliable.

This also adds some log entries for the user to know when a module was reloaded, removing guesswork.

Some unnecessary disk reads (module map) were removed.

Motivation and Context

Users are hitting development scenarios where new builds of modules are not detected and then not reloaded in the running server. The limitations of the Node.js built-in API are important, but are smoothed over by chokidar. However, even chokidar is not accurately emiting events, sometimes due to superseding situations like the modules being docker volume mounts, e.g. https://forums.docker.com/t/file-system-watch-does-not-work-with-mounted-volumes/12038.

How Has This Been Tested?

I've both

Before these changes running on metal would occasionally miss the file writing finishing and not reload, and running in a docker container every change after the first build would be missed. After the changes in this PR I saw every write finish detected.

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (adding or updating documentation)
  • Dependency update
  • Security update

Checklist:

  • My change requires a change to the documentation and I have updated the documentation accordingly.
  • These changes should be applied to a maintenance branch. (Fix: watch local modules other bundles, 5.x.x #1368)
  • This change requires cross browser checks.
  • Performance tests should be ran against the server prior to merging.
  • This change impacts caching for client browsers.
  • This change impacts HTTP headers.
  • This change adds additional environment variable requirements for One App users.
  • I have added the Apache 2.0 license header to any new files created.

What is the Impact to Developers Using One App?

Increased confidence when changes are loaded, and end (or at the very least, greatly decrease) the users having to restart the one-app server to see server bundle changes loaded.

Copy link
Contributor

github-actions bot commented Apr 5, 2024

Size Change: 0 B

Total Size: 232 kB

ℹ️ View Unchanged
Filename Size
./build/app/app.js 38.2 kB
./build/app/app~vendors.js 129 kB
./build/app/runtime.js 5.64 kB
./build/app/service-worker-client.js 5.46 kB
./build/app/vendors.js 54.1 kB

compressed-size-action

return;
}

console.log(`the Node.js bundle for ${moduleName} finished saving, attempting to load`);
Copy link
Member

Choose a reason for hiding this comment

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

As per the logging pr, can this be console.info?

We should only put 1 lot out in general for notifying the user that app has detected a change to a local module. The success, or the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

depends, if the module takes a long time to load it would be useful to the user to know that the process has started

Copy link
Contributor Author

Choose a reason for hiding this comment

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

regarding the logging level, IDK if the change is useful here? #1372 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed the levels in d32878d

Copy link
Contributor Author

@PixnBits PixnBits Apr 11, 2024

Choose a reason for hiding this comment

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

for the log entries, maybe something like

const SAVING_NOTIFICATION_LOAD_WAIT = 500;
...

  const loadNotificationHandle = setTimeout(() => {
    console.info('the Node.js bundle for %s finished saving, attempting to load', moduleName);
  }, SAVING_NOTIFICATION_LOAD_WAIT).unref();

  ...
  newModule = addHigherOrderComponent(await loadModule(
  ...
  
  console.info('finished reloading %s', moduleName);
  clearTimeout(loadNotificationHandle);

?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, I didn't mean for you to make both of these info

The second log, that tells the user something has been reloaded should be log log level still.

This is an important piece of information for the deverloper, and the lack of this notification is currently a point of frustration for Devs.

That said, I really like your time based de-duplicattion here. If all is well, they see 1 log saying success, if it's taking way longer than normal, they see a 'attempting to reload' message, if they then never get the success message they know something is wrong.

In that case, both of these can be log log level.

We just have to be sure that 500ms is the right time budget

code-forger

This comment was marked as off-topic.

rather than string templates, for performance
Comment on lines +29 to +30
const CHANGE_WATCHER_INTERVAL = 1000;
const WRITING_FINISH_WATCHER_TIMEOUT = 400;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

these should be configurable by the user
I'm debating via arguments or environment variables

Copy link
Contributor Author

Choose a reason for hiding this comment

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

perhaps we let that be another PR so as to get this fix in, and then resolve the plan?

Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer arguments. Particularly since this is just local dev. They are much more discoverable since they are self documenting. Also those using one-app-runner will be able to very easily include them in the runner config.

Copy link
Member

@10xLaCroixDrinker 10xLaCroixDrinker left a comment

Choose a reason for hiding this comment

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

What do you think of holding this until Node.js 20 is in, and using fs.watch? It should simplify a lot of this.

There are some caveats to it though.

On Windows, no events will be emitted if the watched directory is moved or renamed. An EPERM error is reported when the watched directory is deleted.

I think this one will be fine.

On IBM i systems, this feature is not supported.

I think this one might be inaccurate, based on the following release note for fs.watch

Version Changes
v19.1.0 Added recursive support for Linux, AIX and IBMi.

On Linux and macOS systems, fs.watch() resolves the path to an inode and watches the inode. If the watched path is deleted and recreated, it is assigned a new inode. The watch will emit an event for the delete but will continue watching the original inode. Events for the new inode will not be emitted. This is expected behavior.

Sounds like if we run into this issue, we may be able to listen for the delete and recreate the watcher.

@10xLaCroixDrinker 10xLaCroixDrinker deleted the fix/watchLocalModules-other-bundles branch May 3, 2024 20:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants