Make watching a bit more resilient to nonatomic bursts of filesystem changes #3009
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I'll apologize in advance for this one. I can't say whether the problem is solves (at least might solve) is generally worth the extra bit of complexity. Anyway, I won't be insulted at all if the answer is no.
I use mill to build static-site generators. Before I generate, I use
mill -w
to serve my soon-to-be-static sites on localhost for edit-refresh cycles on whatever I'll be publishing. It works pretty well, but occasionally, for a variety of reasons, the watch cycles fail, and I have to manually restartmill
. Rather than just tolerate that (it's tolerable!), I wondered whether it wouldn't be better to try to make watching a bit more robust to the kind of conditions that seem to flummox it.The most frequent condition, in my case, has to do with
emacs
lock files. An example error and stack trace is at the bottom of this note. Basically, when I begin to modify a file, emacs creates a lockfile, andmill
restarts harmlessly. That's no problem. But when I save my modified file, emacs first saves, then deletes its lockfile. That sets up a race for mill, which walks source directories, and then hashes in some fashion the files it finds. The walk sometimes occurs before the lockfile is removed, while the attempt to examine the file happens after after, leading to ajava.nio.file.NoSuchFileException
.I don't think this issue is likely to be restricted to emacs. In general, I don't think it's uncommon for filesystem changes to happen in short, nonatomic bursts, so maybe it would be good for watching to be resilient to that.
This PR is kind of a dumb attempt at that. In the happy case, it should have very low overhead. But when an Exception would have occurred due to hitting this kind of race badly, we pause 50 milliseconds, then try again.
50 milliseconds is a guess! The intention is to be short enough not to slow builds down noticeably, but long enough that bursts of sequential filesystem changes are likely to complete before the retry. I don't know for sure that it's a great number. But it does seem like at worst it increases the likelihood of a watch succeeding and otherwise does little harm. I'd obviously be thrilled with better numbers or more sophisticated approaches.
Normally I'd want to log the initial failure somewhere, but I don't know of a logger I can access in
Watchable
, and wasn't sure whether just spewing toConsole.err
is okay.Anyway, for what it's worth!
The example error trace is below: