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
NormalModule.needRebuild cache calculations seem to be wrong for filesystems that don't support millisecond precision mtimes #2003
Comments
Sigh… second-level precision mtimes. Filed webpack/webpack#2003 in relation to the difficulties I was having. Oh, and still need to revisit caching with preventSymlinkResolution on.
This is pretty critical... |
okey, I tried to fix it... but unsure if it's working correctly. Could you run your test agains the webpack master branch with updated watchpack dependency. |
Awesome, thanks. To test I first backported your fix on top of v1.12.13, since there were several other things I'd need to change to get on webpack 2.x. After that, things were almost working, except for a couple small things. I needed this this fix to ensure the timestamps were actual timestamps and summed into ints rather than a concatenated string. And also, I needed to make sure that the timestamp adjustment happened after the After that tiny fix, things are golden 😸. Though I thought I could make the
Those changes look good to you? Let me know if you'd like to me make an actual PR. |
Instead of creating a new timestamp with `new Date().getTime()` (and avoid having to deal with filesystem precision: webpack#2003)
Instead of creating a new timestamp with `new Date().getTime()` (and avoid having to deal with filesystem precision: webpack#2003) Note, depends on a change to webpack-core too.
These tests try to ensure (for filesystems with second-level precision): - A file is not erroneously cached when the file is modified within the same second it was last built (webpack#2003 (comment)) wasn’t good enough - Avoid doing unnecessary builds when a file has _not_ been modified, but another build has been kicked off in the same second it was last built
@sokra, I continued to run into more issues†, so I tried a different approach. Instead of accounting for filesystem accuracy, I tried to instead improve webpack to only refer to and compare actual file mtimes and content hashes‡. I spiked on that, with a couple tests to confirm, over in my fork's Additionally, to more concretely illustrate this issue (and another I found with CachePlugin), I created a webpack-cache-issues example repo with scripts to replicate the cache issues. Note, my proposed code changes are far from perfect. Not only do I not have a full understanding of the whole Webpack code base (for example, are †: The other issue I was running into was that Webpack's previous caching logic (in particular, the logic when directly using the Webpack node API) assumed that the there was little-to-no time elapsed between when he original file modification occurs and when Webpack starts to build the file. Since the Here's one (but not the only) example of how this goes wrong, even if the filesystem has millisecond-level precision:
‡: The main reason why a file mtime is not sufficient for a |
Thanks for the testcases. I added your test case and also added my own tests to the webpack test suite. But they pass without any change to the code (on my computer and on travis). (master branch) So either this was already fixed, or is something specify to your platform. I want to note here that while developing watchpack I already considered file system accurency. I tries to detect accurency automatically and fires more event if it is unsure if a change could have occured. Could you run the webpack tests on your computer to check if this is a platform specific issue? (you need to |
K, here is an example of those master tests failing on my macbook pro (I think that one of these problems is specific to filesystems with second level precision which is very often/always the case on macs these days). Note, I did a fresh, separate clone and clean
|
Also, a couple other things:
Thanks again for looking into this. And @sokra please do not hesitate to let me know how I and my team at HubSpot can help Webpack out! We are incredibly appreciative of all your efforts, and want to do our part to help push community/project forward. |
Ok I was able to reproduce the caching issue by formating a usb stick with FAT32 (2s fs). I also enabled osx build on travis (seem to be new 👍 ), which also shows this issue. Now investigating. If using |
Nice. I'm going to go ahead and try and get travis to build my webpack-cache-issues repo too. |
ok I fixed some issues (purge before cache, typos in CachePlugin). Some stuff was expected to fail (module rebuilds more often on inaccurate file system, because we rebuild if we are unsure if the file was changed). Some stuff is still not working (2 watchpack tests fail, but I need to grab a Mac to fix it (don't own one)). The webpack tests now pass on OSX too and CI runs on OXS too. |
@timmfin Can you still see this issue? |
I'm no longer seeing this specific issue. But that's because we (HubSpot internal build tools) have moved away from a broccoli-based build that calls webpack and are using the webpack cli and/or dev middleware directly. So while this is not specifically an issue for me anymore I'm pretty sure that there is still a core problem with webpack if you are manually starting a compilation via the API (when there is a significant delay between the file's modification time and when some build code manually kicks off a I leave it up to the maintainers if this issue should be closed or not. Even though I do think there is a problem, I don't know how many people are dealing with that case. And I certainly won't be offended, I can't offer up as much time trying to debug/validate an issue that isn't pressing for me anymore. ps: Though, I'm still often running into awkwardness with second-level filesystem precision. However I'm pretty sure that is illustrated and well described by this watchpack issue (this comment in particular). |
see watchpack issue |
I was writing some integrations tests for broccoli-webpack-cached (trying to test that broccoli and webpack caching were working well together) and I was getting pretty unexpected, seemingly non-deterministic behavior. That lead me to digging into how Webpack caches things, namely how:
NormalModule
saves abuildTimestamp
every time a file is builtbuildTimestamp
for each file in needsRebuiltThat all makes sense, but the problem I see is that
buildTimestamp
is saved with millisecond-level precision. However, many filesystems out there (in my case, HFS on OSX) only support second-level precision. So this can happen:13:50:00 and 100ms
(hour, min, second, and ms). That is saved tothis.buildTimestamp
.13:50:00 and 500ms
. But the timestamp saved in thecompiler.fileTimestamps
object has no millisecond precision, so is only13:50:00 and 0ms
13:50:00 and 0ms
) is>=
the previousbuildTimestamp
(13:50:00 and 500ms
) and decides there has not been a file modification. Even though there definitely was a change to the file, it just happened within the same second and was ignored.I verified this problem goes away when I force NormalModule to truncate milliseconds from saved the
buildTimestamp
, like so:But that likely isn't a good change. Ideally, I think that truncation would only happen if we can detect that the input filesystem only has second-level precision (but I didn't look deep how hard/easy that is).
I realize that I am much more likely to run into this issue when writing test code, and that is pretty different than a typical local dev server/watch/build script use-case. But I gotta think that this bug even rears its head in normal scenarios from time to time... well that is unless I've missed something.
ps: Above Webpack github links are to 1.x not 2.x-beta source.
pps: Node didn't always, but now does support millisecond precision for filesystems that support it.
The text was updated successfully, but these errors were encountered: