Skip to content

fix(core) Pass mutex file to yarn classic when installing classic git dependencies#5373

Open
rally25rs wants to merge 3 commits into
yarnpkg:masterfrom
rally25rs:pack-classic-mutex-5349
Open

fix(core) Pass mutex file to yarn classic when installing classic git dependencies#5373
rally25rs wants to merge 3 commits into
yarnpkg:masterfrom
rally25rs:pack-classic-mutex-5349

Conversation

@rally25rs

Copy link
Copy Markdown
Contributor

What's the problem this PR addresses?

fixes #5349

Due to yarn classic not being concurrency-safe by default, there was potential for a cache conflict if multiple yarn classic github dependencies were installed in parallel.

For example 2 github repos that both use yarn classic

"dependencies": {
  "some-yarn-classic-project": "git+ssh://git@github.com:org/some-yarn-classic-project.git",
  "another-yarn-classic-project": "git+ssh://git@github.com:org/another-yarn-classic-project.git"

if they happen to install in parallel, it could lead to a yarn classic ENOENT error during the Fetching packages stage.

...

How did you fix it?

  • Added a new yarnrc config option yarn1MutexFilename that defaults to ./.yarn/.yarn-mutex.
  • When yarn classic is run to install classic deps, --mutex file:... option is passed, using the path from the yarn1MutexFilename setting.

...

Checklist

  • I have set the packages that need to be released for my changes to be effective.
  • I will check that all automated PR checks pass before the PR gets reviewed.

Comment on lines +247 to +251
yarn1MutexFilename: {
description: `When repositories that use yarn1 are included as dependencies, this file is used as a mutex to avoid concurrency issues.`,
type: SettingsType.ABSOLUTE_PATH,
default: `./.yarn/.yarn-mutex`,
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to set the mutex for Yarn Classic I don't see the point of making it configurable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wasn't sure this would always be a writable path. If someone has a locked down user in a docker image with least privilege, it seemed possible they might not have write access to .yarn.
I was just trying to make it flexible. I had also noticed that the global and cache paths are configurable, so thought maybe all the .yarn/* paths were... though looking at it again, it seems stuff like .yarn/releases, /sdks, /plugins etc are not configurable, so maybe yarn just doesn't really work if .yarn isn't a writable path.
I'd be fine removing this config option, but just wasn't sure how configurable to keep this 🤷

// package.json, which I don't want to do to keep the codebase
// clean (even if it has a slight perf cost when cloning v1 repos)
const install = await execUtils.pipevp(`yarn`, [`install`], {cwd, env, stdin, stdout, stderr, end: execUtils.EndStrategy.ErrorCode});
const install = await execUtils.pipevp(`yarn`, [`install`, `--mutex`, mutexPath], {cwd, env, stdin, stdout, stderr, end: execUtils.EndStrategy.ErrorCode});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we instead limit it to one classic install at a time?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 216 has a limit

const MAX_PREPARE_CONCURRENCY = 2;
const prepareLimit = pLimit(MAX_PREPARE_CONCURRENCY);

which could just be set to 1 to avoid this problem, but it isn't separated by package manager type, so setting it to 1 would have a negative perf impact on all installs that use git repos. I wasn't sure the tradeoff was worth it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add another limit for just Yarn classic installs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be a nice way to handle this concurrency issue without having to pass the mutex. I'd certainly prefer to handle the limit in yarn modern.
It seemed like it might be awkward to structure that file to have different limits, since the whole thing is wrapped in one pLimit.
I wasn't sure how make the pLimit more conditional like that... code suggestions welcome.

Comment on lines +2 to +3
"@yarnpkg/cli": minor
"@yarnpkg/core": minor

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit title says fix which makes this a patch but here it's marked as minor, it can't be both.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't aware of the convention. I clicked through some other open PRs and the first 3 other fix( titled PRs also just update patch.
I don't remember seeing suggested title prefixes in the contributing guide. Is there a documented recommended list?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug?]: Yarn runs multiple classic yarn installs on github deps without mutex. Causes cache issue/error.

2 participants