install: honor BUN_CONFIG_MAX_HTTP_REQUESTS - #38744
Conversation
|
Updated 1:57 AM PT - Aug 15th, 2026
✅ @robobun, your commit 3a2a9c87179cdcda5588de5b3ce3dbbbb3f04d55 passed in 🧪 To try this PR locally: bunx bun-pr 38744That installs a local version of the PR into your bun-38744 --bun |
|
Status: reproduced and fixed; ready for review.
|
|
Warning Review limit reached
Next review available in: 7 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
Comment |
There was a problem hiding this comment.
LGTM — small, well-scoped precedence fix.
What was reviewed:
- Traced the three
MAX_SIMULTANEOUS_REQUESTSstores againstasync_http::load_env(AsyncHTTP.rs:205-234) — invalid/zero env values still fall through to the pre-stored install default, and the.max(1)clamp on--network-concurrency 0is preserved. - Checked that moving
env.has_http_proxy()beforeoptions.load()is safe:options.loadonly reads from the already-populatedDotEnvLoaderand does not load additional env sources that could add proxy vars. - Test refactor:
ctx.requestedis the per-context counter incremented by the shared dummy registry (dummy.registry.ts:350),envisbunEnvaliased at import, and theit.eachrows cover flag-only, env-only, and flag-overrides-env.
Extended reasoning...
Overview
Three files: src/install/PackageManager.rs reorders when MAX_SIMULTANEOUS_REQUESTS is written during PackageManager::init so that BUN_CONFIG_MAX_HTTP_REQUESTS (parsed inside options.load → async_http::load_env) is no longer clobbered by the install default; test/cli/install/bun-install.test.ts converts the existing --network-concurrency=5 test into an it.each with two additional rows for the env var alone and for flag-overrides-env; and docs/runtime/environment-variables.mdx clarifies the install default (64) and precedence.
Security risks
None. This adjusts a process-wide concurrency cap for outbound HTTP during bun install. No auth, crypto, path handling, or untrusted-input parsing is touched. The env var parser itself (load_env) is unchanged and already bounds-checks to 1..=65535.
Level of scrutiny
Low-to-medium. The Rust change is a mechanical reordering of three .store(.., Ordering::Relaxed) calls on a static atomic during single-threaded init, before the HTTP thread starts. I verified: (1) load_env only stores when the env value parses to a nonzero u16, so an invalid/zero value now falls back to the install default that was pre-stored — matching the PR description's probe matrix; (2) cli.network_concurrency is Option<u16>, so usize::from(n.max(1)) is the same clamp as the removed n.max(1) as usize; (3) env.has_http_proxy() reads http_proxy/HTTP_PROXY/https_proxy/HTTPS_PROXY from the already-loaded DotEnvLoader, and options.load (PackageManagerOptions.rs:403-672) does not mutate those keys, so calling it before options.load returns the same result as before.
Other factors
The test refactor follows REVIEW.md harness conventions: await using proc, concurrent pipe drain via Promise.all, {...env, ...extraEnv} spread over bunEnv, and a combined-object toEqual assertion. The dropped > 20 throw inside the stub is safe to remove because a thrown handler would have returned a 500 and triggered install-side retries, inflating ctx.requested past 51 — the maxConcurrentRequests <= cap assertion already guards the invariant. The 10 ms Bun.sleep is simulated registry latency (needed for requests to overlap so the peak counter is meaningful), not a wait-for-condition; it's commented as such. The PR description shows the env-var row failing with Received: 51 on the unfixed build and passing with the fix, satisfying the fails-for-the-right-reason requirement.
PackageManager::init stored the --network-concurrency value (or the 64 default) into MAX_SIMULTANEOUS_REQUESTS after options.load had already applied BUN_CONFIG_MAX_HTTP_REQUESTS, so the env var never had an effect on bun install. Store the install default before options.load and only the explicit --network-concurrency value after it, so the precedence is flag, then env var, then default.
00df52c to
3ebff88
Compare
There was a problem hiding this comment.
LGTM — reorders the three MAX_SIMULTANEOUS_REQUESTS stores so the env var isn't clobbered by the install default.
What was reviewed:
- Traced
options.load→async_http::load_env(AsyncHTTP.rs:205–234): only stores when the env var parses to a nonzerou16, so invalid/zero falls through to the install default set just before it. env.has_http_proxy()moved beforeoptions.load—envis passed by shared ref, so the proxy check can't differ between the old and new position;http_thread::initstill runs after all three stores.- Test refactor:
ctx.requestedis the harness's per-context counter (dummy.registry.ts:350), the droppedurlsassertion was dead, and the> 20throw would have caused 500 retries — themaxConcurrentRequests <= capassertion is the real guard.
Extended reasoning...
Overview
The PR fixes BUN_CONFIG_MAX_HTTP_REQUESTS being ignored by bun install. Three files: PackageManager.rs reorders atomic stores in init (default before options.load, CLI flag after, guarded by if let Some); bun-install.test.ts converts the existing --network-concurrency=5 test into an it.each with two new rows (env-only, flag-overrides-env); the docs table row for the env var now states the install default (64) and flag precedence.
Security risks
None. This is init-time ordering of atomic stores to a process-wide concurrency cap. The values themselves are unchanged (same clamp, same default constants), and load_env already validates the env var as a u16 in [1, 65535].
Level of scrutiny
Low-to-medium. The change is a mechanical reordering of three stores with a clear invariant (flag > env > default). I verified: load_env is reached via PackageManagerOptions::load at line 661 and only writes when the env value is valid; env is a &DotEnvLoader throughout so has_http_proxy() returns the same value at the earlier position; the HTTP thread starts at http_thread::init further down, so all three stores land before any request is scheduled. The usize::from(network_concurrency.max(1)) matches the old .max(1) as usize semantics (the type is u16 so usize::from is lossless).
Other factors
The test changes are a strict improvement over the original: the dead urls assertion and unused stdin: "pipe" are gone, pipes are drained concurrently with Promise.all, await using handles cleanup, and ctx.requested reuses the harness counter that other tests in this file already rely on. The Bun.sleep(10) in the stub is simulated registry latency (needed to make requests overlap so peak concurrency is observable) and is commented as such — not a wait-for-condition sleep. The comment-cop bot's feedback about the paragraph-long comment was addressed in 3a2a9c8. The one CI failure (test-http-chunk-problem.js) is unrelated and was picked up via rebase onto #38726.
|
Heads-up from #38759, which fixes the The two branches merge cleanly right now. #38759 puts its registry stub in a module-level helper, |
Problem
BUN_CONFIG_MAX_HTTP_REQUESTShas no effect onbun install: with it set to 8, a loopback registry still sees 64 requests in flight. Only--network-concurrencyworks. Same on 1.3.14; the docs list the variable as applying tobun install.PackageManagerOptions::load(src/install/PackageManager/PackageManagerOptions.rs:661) callsasync_http::load_env, which stores the variable intoMAX_SIMULTANEOUS_REQUESTS.PackageManager::init(src/install/PackageManager.rs, formerly line 2276) then unconditionally stored--network-concurrencyor the 64 default over it.Retry-Afterhandling for 429s inbun install, this variable is the documented way to get past a rate limiting registry, so the documented mitigation was a no-op.Fix
PackageManager::initnow stores the install default (64, or the proxy default) beforeoptions.load, and afteroptions.loadstores only an explicitly passed--network-concurrency. Precedence is therefore flag, then env var, then default.if let Some(network_concurrency)guard on the post-options.loadstore; the values themselves are unchanged (--network-concurrency 0still clamps to 1, an invalid or zero env value still logs and falls back to the default, the same as underfetch).bun installdocs row forBUN_CONFIG_MAX_HTTP_REQUESTSnow states the install default and that--network-concurrencyoverrides the variable.test/cli/install/bun-install.test.ts, "bun install with ... doesnt go over N concurrent requests". The existing--network-concurrency=5case became anit.eachrow (same input and assertions; its 51-dependency package.json is now generated, and the> 20throw inside the stub was dropped because the max assertion already covers it and a thrown 500 would have triggered retries). Two new rows:BUN_CONFIG_MAX_HTTP_REQUESTS=5, which observes 51 requests in flight on the unfixed build and at most 5 with the fix, and--network-concurrency=2together withBUN_CONFIG_MAX_HTTP_REQUESTS=50, which pins the precedence.bun bd test test/cli/install/bun-install.test.ts -t "concurrent requests": 3 pass with the fix; the env var row fails withReceived: 51on the unfixed debug build and on release 1.4.0.bun-install.test.tson the fixed build: the only failures are the 14 tests that need public internet (bitbucket/gitlab/vercel URLs) plusshould support --registry CLI flag, and all of them fail identically on the unfixed build in this environment.Background
MAX_SIMULTANEOUS_REQUESTS(src/http/AsyncHTTP.rs) is the process-wide cap on in-flight HTTP requests. The HTTP thread reads it on every drain, so whatever value is in it when the first request is scheduled is what applies;bun installstarts the HTTP thread later ininit, after both stores.async_http::load_envis the shared parser forBUN_CONFIG_MAX_HTTP_REQUESTS; the runtime (bun run, fetch) calls it directly on top of the static's 256 default, andbun installreaches it throughoptions.load. Layering the install default underneath it, instead of on top of it, is what makes the same function serve both.Probe of the report's matrix against the fixed debug build (80 leaf deps, loopback stub holding each request 30 ms)
Before the fix,
env=8andenv=4 flag=8read 64 and 8 respectively; the other rows are unchanged.no test proof · iteration 0 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/install/bun-install.test.ts