Skip to content

Commit 4001716

Browse files
authored
fix: limit concurrency when generating BUILD files in npm_install and yarn_install (#3509)
* chore: add .gitattributes to ignore changes in generated docs files on PR reviews * fix: limit concurrency when generating BUILD files in npm_install and yarn_install
1 parent c962f12 commit 4001716

6 files changed

Lines changed: 82 additions & 14 deletions

File tree

.gitattributes

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
docs/Built-ins.md linguist-generated=true
2+
docs/Concatjs.md linguist-generated=true
3+
docs/Cypress.md linguist-generated=true
4+
docs/esbuild.md linguist-generated=true
5+
docs/Jasmine.md linguist-generated=true
6+
docs/Karma.md linguist-generated=true
7+
docs/Protractor.md linguist-generated=true
8+
docs/Providers.md linguist-generated=true
9+
docs/Rollup.md linguist-generated=true
10+
docs/Terser.md linguist-generated=true
11+
docs/Toolchains.md linguist-generated=true
12+
docs/TypeScript.md linguist-generated=true

docs/Built-ins.md

Lines changed: 30 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/npm_install/generate_build_file.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ let LEGACY_NODE_MODULES_PACKAGE_NAME = '$node_modules$';
5555
let config: any = {
5656
exports_directories_only: false,
5757
generate_local_modules_build_files: false,
58+
generate_build_files_concurrency_limit: 64,
5859
included_files: [],
5960
links: {},
6061
package_json: 'package.json',
@@ -688,7 +689,7 @@ async function findPackagesAndPush(pkgs: Dep[], p: string, dependencies: Set<str
688689

689690
const listing = await fs.readdir(p);
690691

691-
await Promise.all(listing.map(async f => {
692+
let promises = listing.map(async f => {
692693
// filter out folders such as `.bin` which can create
693694
// issues on Windows since these are "hidden" by default
694695
if (f.startsWith('.')) return [];
@@ -702,7 +703,17 @@ async function findPackagesAndPush(pkgs: Dep[], p: string, dependencies: Set<str
702703
await findPackagesAndPush(pkgs, path.posix.join(pf, 'node_modules'), dependencies);
703704
}
704705
}
705-
}));
706+
});
707+
708+
if (config.generate_build_files_concurrency_limit < 1) {
709+
// unlimited concurrency
710+
await Promise.all(promises);
711+
} else {
712+
while (promises.length) {
713+
// run batches of generate_build_files_concurrency_limit at a time
714+
await Promise.all(promises.splice(0, config.generate_build_files_concurrency_limit))
715+
}
716+
}
706717
}
707718

708719
/**

internal/npm_install/index.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ let LEGACY_NODE_MODULES_PACKAGE_NAME = '$node_modules$';
1313
let config = {
1414
exports_directories_only: false,
1515
generate_local_modules_build_files: false,
16+
generate_build_files_concurrency_limit: 64,
1617
included_files: [],
1718
links: {},
1819
package_json: 'package.json',
@@ -443,7 +444,7 @@ async function findPackagesAndPush(pkgs, p, dependencies) {
443444
return;
444445
}
445446
const listing = await fs_1.promises.readdir(p);
446-
await Promise.all(listing.map(async (f) => {
447+
let promises = listing.map(async (f) => {
447448
if (f.startsWith('.'))
448449
return [];
449450
const pf = path.posix.join(p, f);
@@ -456,7 +457,15 @@ async function findPackagesAndPush(pkgs, p, dependencies) {
456457
await findPackagesAndPush(pkgs, path.posix.join(pf, 'node_modules'), dependencies);
457458
}
458459
}
459-
}));
460+
});
461+
if (config.generate_build_files_concurrency_limit < 1) {
462+
await Promise.all(promises);
463+
}
464+
else {
465+
while (promises.length) {
466+
await Promise.all(promises.splice(0, config.generate_build_files_concurrency_limit));
467+
}
468+
}
460469
}
461470
async function findScopes() {
462471
const p = nodeModulesFolder();

internal/npm_install/npm_install.bzl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,14 @@ Using managed_directories will mean that
359359
default = 3600,
360360
doc = """Maximum duration of the package manager execution in seconds.""",
361361
),
362+
"generate_build_files_concurrency_limit": attr.int(
363+
default = 64,
364+
doc = """Limit the maximum concurrency of npm package processing when generating
365+
BUILD files from the node_modules tree. Unlimited concurrency can lead to too many
366+
open files errors (https://github.com/bazelbuild/rules_nodejs/issues/3507).
367+
368+
Set to 0 or negative for unlimited concurrency.""",
369+
),
362370
})
363371

364372
def _apply_pre_install_patches(repository_ctx):
@@ -466,6 +474,7 @@ def _create_build_files(repository_ctx, rule_type, node, lock_file, generate_loc
466474
generate_config_json = json.encode(
467475
struct(
468476
exports_directories_only = repository_ctx.attr.exports_directories_only,
477+
generate_build_files_concurrency_limit = repository_ctx.attr.generate_build_files_concurrency_limit,
469478
generate_local_modules_build_files = generate_local_modules_build_files,
470479
included_files = repository_ctx.attr.included_files,
471480
links = validated_links,
@@ -475,8 +484,8 @@ def _create_build_files(repository_ctx, rule_type, node, lock_file, generate_loc
475484
rule_type = rule_type,
476485
strict_visibility = repository_ctx.attr.strict_visibility,
477486
workspace = repository_ctx.attr.name,
478-
workspace_rerooted_path = _WORKSPACE_REROOTED_PATH,
479487
workspace_rerooted_package_json_dir = paths.normalize(paths.join(_WORKSPACE_REROOTED_PATH, package_json_dir)),
488+
workspace_rerooted_path = _WORKSPACE_REROOTED_PATH,
480489
),
481490
)
482491
repository_ctx.file("generate_config.json", generate_config_json)

npm_deps.bzl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,24 +163,28 @@ js_library(
163163
},
164164
package_json = "//internal/linker/test/multi_linker/test_a:package.json",
165165
yarn_lock = "//internal/linker/test/multi_linker/test_a:yarn.lock",
166+
generate_build_files_concurrency_limit = 0,
166167
)
167168

168169
yarn_install(
169170
name = "internal_test_multi_linker_test_b_deps",
170171
package_json = "//internal/linker/test/multi_linker/test_b:package.json",
171172
yarn_lock = "//internal/linker/test/multi_linker/test_b:yarn.lock",
173+
generate_build_files_concurrency_limit = 0,
172174
)
173175

174176
yarn_install(
175177
name = "internal_test_multi_linker_test_c_deps",
176178
package_json = "//internal/linker/test/multi_linker/test_c:package.json",
177179
yarn_lock = "//internal/linker/test/multi_linker/test_c:yarn.lock",
180+
generate_build_files_concurrency_limit = 0,
178181
)
179182

180183
yarn_install(
181184
name = "internal_test_multi_linker_test_d_deps",
182185
package_json = "//internal/linker/test/multi_linker/test_d:package.json",
183186
yarn_lock = "//internal/linker/test/multi_linker/test_d:yarn.lock",
187+
generate_build_files_concurrency_limit = 0,
184188
)
185189

186190
yarn_install(
@@ -189,6 +193,7 @@ js_library(
189193
args = ["--production"],
190194
package_json = "//internal/linker/test/multi_linker/lib_b:package.json",
191195
yarn_lock = "//internal/linker/test/multi_linker/lib_b:yarn.lock",
196+
generate_build_files_concurrency_limit = 0,
192197
)
193198

194199
yarn_install(
@@ -197,6 +202,7 @@ js_library(
197202
args = ["--production"],
198203
package_json = "//internal/linker/test/multi_linker/lib_c:lib/package.json",
199204
yarn_lock = "//internal/linker/test/multi_linker/lib_c:lib/yarn.lock",
205+
generate_build_files_concurrency_limit = 0,
200206
)
201207

202208
yarn_install(

0 commit comments

Comments
 (0)