Commit Graph

94 Commits

Author SHA1 Message Date
Ben Newman
6055b49f8d Wait on removal of garbage directories.
This would have been a nice optimization if it had worked, but (in
addition to leaving garbage directories lying around sometimes if the
process was killed), it appears to have some unintended consequences for
meteorNpm.rebuildIfNonPortable and related functions, since the garbage
directories are easily confused for npm package directories.

Example stack trace:

  Error: ENOENT: no such file or directory, open '/home/travis/build/meteor/galaxy-server/node_modules/heapdump-garbage-1c2jqib/package.json'
      at Error (native)
   => awaited here:
      at Promise.await (/home/travis/.meteor/packages/less/.2.7.9.9fh5c1++os+web.browser+web.cordova/plugin.compileLessBatch.os/npm/node_modules/meteor/promise/node_modules/meteor-promise/promise_server.js:39:12)
      at copyFileHelper (/tools/fs/files.js:633:6)
      at Object.files.cp_r (/tools/fs/files.js:532:7)
      at /tools/isobuild/meteor-npm.js:393:11
      at Array.forEach (native)
      at copyNpmPackageWithSymlinkedNodeModules (/tools/isobuild/meteor-npm.js:386:29)
      at /tools/isobuild/meteor-npm.js:325:5
      at Array.forEach (native)
      at Object.rebuildIfNonPortable (/tools/isobuild/meteor-npm.js:315:17)
      at NodeModulesDirectory.rebuildIfNonPortable (/tools/isobuild/bundler.js:273:22)
      at /tools/isobuild/compiler.js:650:13
2017-04-07 16:21:43 -04:00
Jesse Rosenberger
ae35f13ed2 Use new rm_recursive_async to cleanup garbage directory w/o waiting. 2017-04-06 20:18:38 +03:00
Jesse Rosenberger
960e78c250 Sacrifice atomicity in the event that the file-system won't allow it.
/cc @benjamn
2017-04-06 19:56:17 +03:00
Jesse Rosenberger
e9a2f6d22c Just Profile the *Atomically functions directly.
...Versus reassigning them immediately after.

 (Whitespace-only view is recommended, due to indentation change)
2017-04-06 19:30:06 +03:00
Jesse Rosenberger
af1bc232d6 Hoist "Can we Fiber?" logic up to a helper function.
This also makes it possible to disable it in places where we were not
checking against the `METEOR_DISABLE_FS_FIBERS` env. variable, like in
`rm_recursive`.
2017-04-06 17:17:56 +03:00
Jesse Rosenberger
9e0f61c4b3 Revert "Use fs.move() from fs-extra to fix EXDEV cross device error in docker builds. (#8491)"
Unfortunately, `fs-extra` is still not as perfect at handling various
file system conditions as would be ideal.  It seemed sensical to try and
use a library like this however, it turns out that the Meteor suite
of file system functions stands up best on Windows, which is where I
encountered most problems.

For example, `fs-extra` still tries to create symlinks as an unprivileged
user – a forbidden task on Windows unless running as Administrator.

In addition, I ran into a constant stream of other errors: `ENOTEMPTY`,
`EBUSY`, `EEXIST` – all for various reasons.

My current recommendation is that we remove `fs-extra` and replace the
`Builder#complete` `renameDirAlmostAtomically` call (which does not
absolutely _have_ to be done atomically) with a `try`/`catch` which
resorts to a basic copy if `err.code === 'EXDEV'`.  All other
functionality stays the same.

This reverts commits:

* d49f3e2704
* 3257bafc84
* 74cb8ebdc2
* 5bbdcc9baa
* 6a0767bbac
2017-04-06 06:50:03 +03:00
Jesse Rosenberger
6a0767bbac Don't reassign, just Profile the *Atomically functions directly. 2017-04-05 19:04:22 +03:00
Jesse Rosenberger
5bbdcc9baa Change order that functions are defined so move is wrapped correctly. 2017-04-05 18:56:05 +03:00
Jesse Rosenberger
74cb8ebdc2 Improve fs-extras move calls for Windows platform. (#8560)
* Improve `fs-extra.move` calls for Windows platform.

This is a follow-up to meteor/meteor#8491 which worked properly on Unix
platforms, but failed in a variety of ways on Windows due to its lack
of Fiber-awareness and desire to create symlinks as unprivileged users
(something not always possible on Windows).

The Fiber issue was observed when trying to remove "src" directories
within the `move` function (which tries a variety of OS/OS/arch-specific
techniques to accomplish its goal) after they had been copied to "dest".
On Windows, this resulted in `EDIRNOTEMPTY` errors since Windows appears
to temporarily cache the file-handle or doesn't release the file-handle
until the next tick.

The symlink issue will hopefully improve in an upcoming release of
Windows (Creator Edition) when Microsoft makes it possible to create
symlinks as an unprivileged user, however it will still require enabling
"Developer" mode in Windows settings.  This implements the same catch
which was already in place for `fs.rename` on the `fs.move` provided by
`fs-extra`.

Performance gains were the same in tests comparing before and after
these changes.

Relates to:
https://github.com/meteor/meteor/issues/8558#issuecomment-291194385

* A few code-cleanups to my original commit.
2017-04-05 12:58:32 +03:00
Jesse Rosenberger
3257bafc84 Change wrapFsFunc for "move" to acknowledge _both_ arguments as paths.
The `wrapFsFunc` function accepts an array of indexes indicating which
arguments are paths.  This is particularly important on Windows, due to
the path-conversation which takes place on those strings.

The docs say:
> Indices of arguments that have paths, these arguments will be
> converted to the correct OS slashes

This follows up on the change made from meteor/meteor#8491 which failed
in our release pipeline when publishing for the Windows architecture
for `1.4.4-rc.3`.
2017-03-30 01:46:42 +03:00
Jeremy Shimko
d49f3e2704 Use fs.move() from fs-extra to fix EXDEV cross device error in docker builds. (#8491)
Use fs.move to fix EXDEV cross device error in docker builds.

Fixes #7852.
2017-03-28 15:53:22 +03:00
Jesse Rosenberger
6bbd432081 Be more understanding of Windows' filesystem limitations.
Presently, the renaming of directories that are in-use will fail on
Windows.  This is already compensated for when `process.platform` is
set to `win32`.  However, within BashOnWindows/WSL (Windows Subsystem
for Linux), `process.platform` is equal to `linux`, though the
underlying filesystem is still the same.

Microsoft has stated that it is unlikely that they will remove
`Microsoft` from the `os.release()` value so we check for that.
2017-03-22 20:35:43 +02:00
Jesse Rosenberger
17a786eb36 Ensure that .bin files maintain executable bits in Windows bundles.
Windows has no concept of the executable bit so it is not applied by the
`fstream` `Reader` when building the tarball which is used in both
`meteor build` and `meteor deploy`.  For Windows users, this causes
important scripts (such as `node-pre-gyp`) to not be executable when
the bundles are deployed to Unix platforms (such as Galaxy).

To avoid giving every file executable bits, this applies an executable
bit to the file only if it has read permission (something Windows _is_
aware of) and if it is in a location that Node bin links are typically
placed, the `/node_modules/.bin/` directories.
2017-03-21 12:19:08 -04:00
Ben Newman
e4c7b0890c Watch all imported files in linked npm packages on server. 2016-11-14 14:25:22 -05:00
Ben Newman
8d1133743d Fix options.transformFilename behavior in files.cp_r.
The options.transformFilename function is only supposed to transform
target file names, not the names of source files to be copied.

This behavior was broken by c5809a4a1c
between Meteor 1.4.0.1 and 1.4.1. Thank goodness for `git bisect`!

The biggest symptom of this mistake was that `meteor create --package`
no longer created files based on the ~fs-name~.js and ~fs-name~-tests.js
template files.

This probably merits a 1.4.1.4 release in addition to 1.4.2.2.
2016-11-14 11:50:50 -05:00
Ben Newman
a43d66991b Allow watch.sha1 to accept multiple arguments. 2016-11-08 13:48:23 -05:00
Ben Newman
a7ac32e00a Tolerate ENOENT errors in Builder#copyDirectory. 2016-11-08 13:33:20 -05:00
Ben Newman
909419b36e Optionally tolerate SyntaxError in optimisticReadJsonOrNull. 2016-11-02 13:04:09 -04:00
Ben Newman
ca4baed90a Disable yielding for files.* operations unless explicitly un-disabled.
Set METEOR_DISABLE_FS_FIBERS=false to un-disable files.* fibers if you
suspect this commit has introduced a problematic difference in behavior.

cc @veered
2016-10-31 21:33:39 -04:00
Ben Newman
f5c61de2fa Fix watching of @scoped, linked npm packages.
https://github.com/meteor/meteor/issues/7978#issuecomment-257056243

Part of #7978.
2016-10-31 12:38:59 -04:00
Ben Newman
bf5f635ac7 Remove optimisticIsSymbolicLink-specific logic from shouldWatch. 2016-10-28 18:16:09 -04:00
Ben Newman
45bb2898fa Watch all paths in linked npm packages.
Fixes #7978.
2016-10-28 17:55:58 -04:00
Ben Newman
45626b699b Support METEOR_DISABLE_FS_FIBERS to help @veered debug fiber storms. 2016-10-25 10:07:42 -07:00
Ben Newman
0d3c74d11c Only call watchersByIno.set(ino, entry) if ino > 0. 2016-10-21 21:39:39 -04:00
Ben Newman
35da19ab4e Avoid "The handle(...) returned by watching..." errors on Linux.
It's a shame that Pathwatcher issues this warning using console.error,
without taking any verbosity options into account:
https://github.com/atom/node-pathwatcher/blob/7ef76e5dfd/src/main.coffee#L53

Fortunately, I believe I've identified the underlying reason why this
happens, which may help resolve the following issue:
https://github.com/atom/node-pathwatcher/issues/98

If all goes well, I'll submit an upstream pull request.

I've also reinstated an old file watching test that I mistakenly removed
when I attempted to switch to chokidar instead of pathwatcher.
2016-10-21 21:14:44 -04:00
Ben Newman
48a2ccbde7 Dirty optimistic functions when node_modules directories change.
This is a bit different from the previous strategy of invalidating
optimistic functions for specific npm package names.

Now, whenever we make changes to the contents of a specific node_modules
directory, or whenever the developer independently modifies an app's
node_modules directory, all optimistic results derived from paths
contained within that node_modules directory will be marked as dirty, and
thus may need to be recomputed.

This strategy prioritizes starting fewer watchers (just one per
node_modules directory) while still allowing npm packages to be added or
removed while the app is running:

  https://github.com/meteor/meteor/pull/7668#issuecomment-255120373

The drawback is that changes within subdirectories of node_modules will
not be detected until the server is fully restarted, but that seems like
an acceptable tradeoff, since npm packages change much less often than
application code.
2016-10-21 20:06:23 -04:00
Ben Newman
e50d916709 Don't swallow JSON.parse SyntaxErrors in optimisticReadJsonOrNull. 2016-10-21 14:00:13 -04:00
Ben Newman
6c501b0148 Respect $METEOR_DISABLE_OPTIMISTIC_CACHING for debugging purposes. 2016-10-18 14:25:07 -04:00
Ben Newman
320874989f Implement and use optimisticReadJsonOrNull for better caching.
The problem with optimisticReadFile is that it doesn't cache anything when
the file is missing, because files.readFile throws an ENOENT exception.
2016-10-18 14:05:52 -04:00
Ben Newman
30d9a57f0d Allow dirtying optimistic functions by npm package name or path. 2016-10-18 13:26:06 -04:00
Ben Newman
ec34a4ecc6 Fix tests by making sure to close optimistic file watchers.
If a test process does not explicitly call process.exit, pathwatcher
watchers may keep it alive indefinitely (either that, or there's a bug
with the persistent:false option to fs.watchFile).

This accidental immortality can be prevented by explicitly closing all
watchers when we no longer have any interest in file change notifications.
2016-10-13 14:09:16 -04:00
Ben Newman
56de90e440 Switch back some optimistic functions in tools/fs/watch.js.
In particular, optimisticReaddir was getting called before relevant dirty
callbacks were firing, and thus failing to notice actual changes on the
file system.

In general, the tools/fs/watch.js code is the one place where we really
need an up-to-date view of the file system. Put another way, if optimistic
functions worked perfectly, we wouldn't need to rely so much on WatchSet
logic, but for now it's a balance of equally important strategies, and we
shouldn't be compromising one by intermingling it with the other.
2016-10-12 18:12:16 -04:00
Ben Newman
1d375ffb70 Hold off on using optimistic functions in watch.readAndWatchFileWithHash.
This partially reverts commit 96c95629eb.

When running `meteor update`, we call writeReleaseFileAndDevBundleLink
immediately before reading .meteor/release, so there's no time for a file
change notification to invalidate the cached contents of that file.

In the future, we could perhaps call optimisticReadFile.dirty(path) as a
consequence of files.writeFile(path, ...), but that may be tricky.
2016-10-11 11:25:36 -04:00
Ben Newman
b594b460a4 Go back to using pathwatcher.watch, with new rewatching logic.
Judging from the variety and extent of test failures, switching to
chokidar.watch was too drastic a change for this late-beta stage of the
release cycle.

The problem with pathwatcher.watch was that watches don't survive the
deletion of the watched file, because (like fs.watch) it watches files
based on inodes, not paths. This problem can be solved in a relatively
narrow way, by attempting to rewatch the file after any "delete" or
"rename" events.
2016-10-11 10:02:06 -04:00
Ben Newman
b814311266 Catch async chokidar.watch errors and suggest raising watch limit. 2016-10-10 17:39:17 -04:00
Ben Newman
0311e76673 Bring back fs.watchFile fallback when chokidar.watch fails.
Especially on Linux, chokidar.watch tends to throw ENOSPC errors when too
many files are being watched.

I removed this logic earlier because I thought chokidar could handle such
failures by itself, but that was wishful thinking.
2016-10-10 17:12:53 -04:00
Ben Newman
96c95629eb Use optimistic functions throughout tools/fs/watch.js. 2016-10-10 15:22:53 -04:00
Ben Newman
117b1a8525 Use chokidar for file watching instead of pathwatcher.
Healthy competition among fs.watch wrappers appears to have produced a
clear winner: https://www.npmjs.com/package/chokidar

This wrapper is better for Meteor than pathwatcher was, because it can
watch directory trees recursively, and it has no trouble watching
nonexistent file paths, whereas pathwatcher would throw an exception.
2016-10-10 14:12:51 -04:00
Ben Newman
1e5b414e48 Prepare for breaking API change affecting optimistic subscribe functions.
As of optimism@0.3.0, the value of `this` within subscribe functions is no
longer the optimistic wrapper function object (instead: null or global, as
if called with no receiver object), so we need to retain a reference to
the optimistic function so that the watcher can call .dirty(...args).
2016-10-10 11:47:19 -04:00
Ben Newman
d0f093413c Use optimisticStatOrNull in tools/fs/watch.js. 2016-10-03 22:19:13 -04:00
Ben Newman
23d62408b2 Use my optimism npm package to implement optimistic functions. 2016-10-03 17:32:10 -04:00
Ben Newman
bfa3eaa57d Use async rimraf as a fallback if rimraf.sync throws ENOTEMPTY.
This change preserves the performance benefits of my previous commit
5af59c58bc, since rimraf.sync is still
attempted first.
2016-09-29 19:25:32 -04:00
Ben Newman
9304f76b52 Fix tests by avoiding printing inotify warning when Console.isHeadless(). 2016-09-27 11:09:46 -04:00
Ben Newman
0d3466b882 Be more defensive when terminating watchers. 2016-09-27 10:41:40 -04:00
Ben Newman
ea92d83744 Don't cache exceptions in optimistic functions.
I originally added the exception-caching functionality in order to avoid
calling files.stat repeatedly for files known to be missing, but now that
we're using statOrNull, knowledge of missing files (as indicated by
statOrNull returning null) is being properly cached.

The reason it's dangerous to cache exceptions is that (for example) when
an ENOENT exception indicates the file is missing, there will be no more
change events for that file, effectively making the exception permanent,
even if the file comes to exist at a later time.
2016-09-27 10:13:19 -04:00
Ben Newman
c7b8b72e77 Never yield in files.symlink. 2016-09-26 20:04:30 -04:00
Ben Newman
5af59c58bc Always use rimraf.sync in files.rm_recursive. 2016-09-26 20:04:30 -04:00
Ben Newman
978df6e043 Use optimistic functions in meteorNpm.isPortable. 2016-09-26 20:04:29 -04:00
Ben Newman
d954415752 Add profiling to PathWatcher watch function. 2016-09-26 20:04:29 -04:00
Ben Newman
83e7b38779 Break circular dependency between {files,watch,optimistic}.js. 2016-09-26 20:04:28 -04:00