-
-
Notifications
You must be signed in to change notification settings - Fork 70
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
feat: relative cache support #114
base: main
Are you sure you want to change the base?
Conversation
Hi @cs6cs6!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.
To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page. Read more about contributing to ESLint here |
Hello. How do I draw attention to this PR? I believe I am only awaiting feedback. |
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.
Thanks for putting this together and sorry for the delay -- we are a small team and have a lot to do.
Overall I think this looks good. I left some feedback throughout.
14475ae
to
1bcafba
Compare
…oss developers or into ci machines. (#16493)
…che and the new cache would look like.
…based on feedback.
a05d10b
to
0b7542c
Compare
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.
This is looking good. Left comments throughout on areas we can clarify and clean up.
|
||
I originally planned the shareable-cache flag so that users of eslint could not be surprised by changed cache behavior, and would also not have to regenerate their cache | ||
for a patch version change. But I discovered by testing that there is no way to NOT force people to regenerate their eslint cache with this change. That's because by adding | ||
the 'shareable-cache' flag, it adds a property to the ConfigArray object. Even if it's set to false (the old behavior), the object's structure changes with a new property |
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.
How is this changing the ConfigArray
? This setting is at the CLI level, not at the config level, so there shouldn't be any changes to the ConfigArray
.
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 object itself, along with all of its properties (set or not) is rolled into the computed hash code that goes into the file. So, simply by adding a new property, the hash computed of the object changes, even if that property is deliberately set to create no change in behavior.
Accepting code review suggestion where backticks are added for readability. Co-authored-by: Nicholas C. Zakas <[email protected]>
Per code review, adding backticks for readability. Co-authored-by: Nicholas C. Zakas <[email protected]>
- `lib/cli.js`: Add the `shareableCache` option, defaulted to false, in the `translateOptions `function. | ||
|
||
### Changing cache file serialization | ||
- `lib/cli-engine/lint-result-cache.js`: Add the properties `cwd` and `shareableCache` to the `LintResultCache` class. `cwd` is a string, the current working directory. `shareableCache` is a boolean, the result of the user's passed in command line parameter. Use these values in two main places: |
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 we should clarify what we mean by the current working directory that will be passed to the LintResultCache
class. Is it process.cwd()
, or cwd
that was passed to ESLint/FlatESLint constructor? In the latter case, is there a way to pass cwd
to file-entry-cache
or we could end up calculating paths differently?
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.
Another question is does file-entry-cache
support relative paths? All tests seem to be with absolute paths:
https://github.com/jaredwray/file-entry-cache/blob/master/test/specs/cache.js
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.
It will. I am just going to push up the code review sometime today. I have a complete and working branch on this task, and most of your questions wuold be resolved by the code review/better answered looking at the code changes.
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.
Don't forget to answer the question regarding what cwd
is from the previous comment.
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.
Is it
process.cwd()
, orcwd
that was passed to ESLint/FlatESLint constructor?
When created in cli-engine.js, it's options.cwd. It is also referred to as 'cwd' in the code.
When created in flat-eslint.js, it's processedOptions.cwd.
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.
Do you think that
cwd
would be a better base location to store relative paths?Do you mean in all cases? If so, the answer is no. I think it makes the most sense to have it relative to the cache file when
--cache-location
is not used.
I'm asking because when --cache-location
is not set, the cache file location should be already cwd
. I think the advantage of keeping the paths relative to the cache file directory is that they don't change if the current directory changes, for example in a monorepo. Do you have a particular scenario in mind where storing paths relative to cwd
would be advantageous?
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.
Yeah, as @fasttime noticed, when --cache-location
is not used, the cache file defaults to .eslintcache
in cwd. So if the logic would be to use the location of the cache file when --cache-location
is not used, and cwd when --cache-location
is used, then it's basically the same as - always use cwd.
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.
For a use case where a monorepo has a single eslint cache file that's checked-in and shared between developers, and developers work and run eslint in project subdirectories (using --cache-location
with a path to the single cache file somewhere in the root), I believe the only solution would be that the paths are relative to the cache file directory.
For other use cases, e.g., when the cache file is generated in CI and shared between CI runs (I believe that was the original use case in eslint/eslint#16493?), I'm not sure, it depends on where and how the cache file will be stored and used. It might be good to get more input from people requesting this feature.
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 we should just make a decision and see what happens when people test with it. This PR has been open since October of last year, and it seems like this is the last thing to decide on, so I don't think there's value in drawing this out further when we have a binary decision to make.
So I'd like to propose that we say the paths are always relative to location of the .eslintcache
file.
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.
So I'd like to propose that we say the paths are always relative to location of the
.eslintcache
file.
I agree.
@cs6cs6 there were still some outstanding requests for you to consider here. Are you still working on this? |
@cs6cs6 just checking back to see if you intend on finishing this up? |
Hello, I apologize for the delay. I am working on this today. |
@nzakas and @mdjermanovic let me know if you need any other changes or if you want file-entry-cache to work a different way with an example. |
@mdjermanovic I think you were the last one to look at |
@mdjermanovic just let me know anything you want changed and I can do it. |
@jaredwray thanks for the support! I believe we'll need some changes or new features in |
```js | ||
function hashOfConfigFor(config, cwd) { | ||
if (!configHashCache.has(config)) { | ||
// replace the full directory path in the config string to make the hash location-neutral |
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.
Since this feature will only be implemented for the new config system, I believe there is no need for this because there are no absolute paths in configs.
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.
A place where we do have absolute paths is LintResult#filePath
, so that's something we'll need to convert from absolute to relative and vice versa when cache entries are stored and retrieved.
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.
A place where we do have absolute paths is
LintResult#filePath
, so that's something we'll need to convert from absolute to relative and vice versa when cache entries are stored and retrieved.
Or, we could omit LintResult#filePath
property from cache entries and add it back when cache entries are retrieved.
I see that the latest file-entry-cache v9 resolves relative paths passed to What does everyone think about the following solution to support relative paths? We're currently initializing cache this way: this.fileEntryCache = fileEntryCache.create(
cacheFileLocation,
void 0,
useChecksum
); We could pass another argument, this.fileEntryCache = fileEntryCache.create(
cacheFileLocation,
void 0,
useChecksum,
relative
); When
|
Here a stackblitz demonstration of what we'd like to achieve: https://stackblitz.com/edit/stackblitz-starters-axsbxs?file=package.json |
I think hardcoding of |
Yep, will get this added in this week! |
awesome. Will work on this now and should have it released this week |
I did a pull request as I think we will want to just set the relative path at the constructor instead of passing in a boolean as we can check if it is an absolute path or not. Please let me know if this does the fix you want. |
This doesn't seem to solve the problem, as the cache keys are still absolute paths. So when everything is moved to another location, the cache file becomes unusable because it contains entries for absolute paths that no longer exist, and the files that were cached now have different absolute paths. |
@jaredwray just checking if you need more clarification on the use case we're trying to support. |
@jaredwray just checking in to see if @mdjermanovic's comments make sense? |
it does make sense and I am working on a new version that does not use absolute paths. Should be ready by the 19th. |
@jaredwray awesome. Thanks so much. We'll check back then. |
@nzakas and @mdjermanovic - I released v9.1.0 of const path = require('node:path');
const fileEntryCache = require('file-entry-cache');
const cacheFileLocation = path.resolve(__dirname, '.eslintcache');
const useChecksum = true;
const currentWorkingDirectory = __dirname;
const cache = fileEntryCache.create(
cacheFileLocation,
undefined,
useChecksum,
currentWorkingDirectory
); Thanks for the patience on this and I believe this should un-block you with this where you want to rename the working folder and still use the cache. |
@jaredwray thanks for the new versions! Question: how to store file locations relative to the cache file? I tried the following: const fileEntryCache = require("file-entry-cache");
const path = require("node:path");
const cacheFileDir = path.resolve(__dirname, "cache");
const cacheFileLocation = path.resolve(cacheFileDir, ".eslintcache");
const useChecksum = true;
const currentWorkingDirectory = cacheFileDir;
const cache = fileEntryCache.create(
cacheFileLocation,
undefined,
useChecksum,
currentWorkingDirectory
);
const filePath = path.resolve(__dirname, "src", "my-file.js"); // exists
const fileDescriptor = cache.getFileDescriptor(filePath);
fileDescriptor.meta.results = { foo: "bar" };
cache.reconcile();
[{}] |
Do you have a project that I can see with this? I believe the paths are causing issues on this and one thing to look at is that with using the |
In the unit test, all paths are absolute, as they're produced by |
Here a stackblitz repro: https://stackblitz.com/edit/stackblitz-starters-eh4ubs?file=test.js |
The fix for this is to point at the current working directory of where the file is instead of the cache directory: https://stackblitz.com/edit/stackblitz-starters-ikrcmu?file=test.js,cache%2F.eslintcache
The |
@mdjermanovic, @nzakas - I wanted to update you that we have released a new major version of Read the new docs here: https://www.npmjs.com/package/file-entry-cache I would recommend that you continue to do absolute paths like you have done before. We do support When a folder changes you can now call const fileEntryCache = require('file-entry-cache');
const cache = fileEntryCache.create('.eslintcache', undefined, true);
const fileEntry = cache.getFileDescriptor(path.resolve(__dirname, './src/test-file.js');
console.log(fileEntry.changed); // true, first time run
cache.reconcile(); // save to the file cache
// rename the `src` folder as an example
const oldPath = path.resolve(__dirname, './src');
const newPath = path.resolve(__dirname, './src2');
fs.renameSync(oldPath, newPath);
// update all the keys
cache.renameAbsolutePathKeys(oldPath, newPath);
// they are now updated in memory, update the disk cache
cache.reconcile(); There are more updates around this with a faster caching layer and more robust features that you can read about at the README: https://github.com/jaredwray/cacheable/blob/main/packages/file-entry-cache/README.md Please let me know how I can help to make this happen. If you want to do a video conference just let me know. https://fantastical.app/jaredwray/30-minute-sync |
A problem with this is that we don't know |
To clarify, the example with renaming the directory was made to simplify the repro. The use case this RFC targets is when the cache file is created/updated on one machine, and then should be used on another machine where the project is possibly cloned into a different path so the absolute paths of files are different. We think the only way to achieve this is by storing relative instead of absolute paths in the cache file. |
In this example, the cache key for the file is |
@mdjermanovic @jaredwray at this point it seems better to open an issue to contain this back-and-forth instead of continuing on in this RFC. What do you think? |
Who can I work with on this to get it completed? More than happy to schedule a time as with the new file-entry-cache this should be really easy and less work. |
I think @mdjermanovic is the best person to work with. |
…velopers or into ci machines.
Summary
Related Issues