-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
fix: check cache file existence before deletion #19648
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
Conversation
✅ Deploy Preview for docs-eslint canceled.
|
CI is failing because of this PR |
It's passing now, seems like it has been fixed by another PR. |
Yeah he reverted the change and released a new version 🎉 |
tests/lib/eslint/eslint.js
Outdated
fsp.unlink.calledWithExactly(cacheFilePath), | ||
fsp.unlink.notCalled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, for this particular test case, we'd now need the cache file to exist, and write another test for the change made in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if the cache file existed then it will throw an error? I pushed a test case to demonstrate this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it generally should throw an error, but when we set unlink
to throw EROFS
, we're simulating the case where the cache file has been removed in the meantime (assuming we want to keep supporting that scenario, as being discussed in #19648 (comment)), in which case it shouldn't throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see now. We should additionally make sure that the file has been removed if we want to test the code in catch
.
try { | ||
await fs.unlink(cacheFilePath); | ||
if (existsSync(cacheFilePath)) { | ||
await fs.unlink(cacheFilePath); | ||
} | ||
} catch (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if the try-catch is still necessary after this change. It looks like the situations the catch block was intended to address—when the cache file was missing on a writable file system or when it was missing on a read-only file system—are now both handled by the existsSync
check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first version of this code (in cli-engine.js
) was actually a simple if (!options.cache && fs.existsSync(cacheFile)) { fs.unlinkSync(cacheFile); }
without try-catch, but has been changed to the try-catch version in #11546, I believe for the reasons explained in #11946 (comment) in a later PR (the original commit is gone, but it seems the comment is under code that was intending to remove try-catch). My understanding of the reasoning is that if it happens that the cache file disappears between two fs commands, this should not throw an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding of the reasoning is that if it happens that the cache file disappears between two fs commands, this should not throw an error.
Yes, I also think that's what that comment is saying. I was actually considering that the existsSync
check will skip nearly all cases where unlink
would currently reject with an error, including, but not limited, to those tested in the try-catch block. So for example existsSync
will return false if a user has no permission to read a directory, or if a network drive is not found on Windows, or if an I/O error (e.g. a hardware problem) occurs, etc. By contrast, unlink
rejects with different error codes in all these cases. This means that by checking existsSync
in advance as it's done in this PR, these cases will no longer produce an error. It seems redundant at this point to test for error codes ENOENT
and EROFS
specifically in the catch block, when other errors are supposed to be swallowed as well. If a concern is that the file system could change during fs
calls then maybe we could repeat the existsSync
in the catch block:
try {
if (existsSync(cacheFilePath)) {
await fs.unlink(cacheFilePath);
}
} catch (error) {
if (existsSync(cacheFilePath)) {
throw error;
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinion aligns with fasttime's entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM if we want to catch race conditions when attempting to delete the file. Leaving open for @mdjermanovic to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Prerequisites checklist
What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[x] Bug fix (template)
[ ] New rule (template)
[ ] Changes an existing rule (template)
[ ] Add autofix to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:
What changes did you make? (Give an overview)
This PR modifies the cache file deletion logic to check if the cache file exists before attempting to delete it.
Closes #19647
Is there anything you'd like reviewers to focus on?