test: add shared plugin version resolver#9019
Conversation
Generating the versions/ workspace tree is thousands of mkdir/writeFile calls; an unbounded Promise.all over the whole tree exhausts file descriptors (EMFILE). This adds a reusable worker-pool map that bounds in-flight work while preserving input order, and wires `test:scripts` so it runs in CI.
Overall package sizeSelf size: 6.32 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.2.0 | 104.26 kB | 843.44 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
BenchmarksBenchmark execution time: 2026-06-24 20:09:00 Comparing candidate commit ad32570 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 1952 metrics, 13 unstable metrics.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 54c1fd2fa2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
With concurrency > 1, a worker already in flight kept looping and taking new items after a sibling worker rejected, so the helper scheduled further writes while the returned promise had already rejected. A caller that catches the rejection and starts cleanup or retry then races those writes. A shared failure flag now gates the worker loop, so no worker takes a new item once any worker fails.
🎉 All green!🧪 All tests passed 🔗 Commit SHA: ad32570 | Docs | Datadog PR Page | Give us feedback! |
bengl
left a comment
There was a problem hiding this comment.
This seems to not be used anywhere yet?
withVersions() and the install script each expand a module's declared versions into the set of folders to test/install, and the two computations drifted, so a folder could be installed but never tested (or the reverse). This adds a single resolvePluginVersions/getVersionList that both consume: per declared range it pins the lowest supported version exactly and adds the newest of every major the range spans, keyed by the bare major. Covering each major (not the raw range, which only resolves to the newest of the whole range) makes sure the floor major's latest is tested too. `*` collapses to the latest major, and an empty or unparseable entry throws instead of being skipped.
…9022) * test: add shared plugin version resolver withVersions() and the install script each expand a module's declared versions into the set of folders to test/install, and the two computations drifted, so a folder could be installed but never tested (or the reverse). This adds a single resolvePluginVersions/getVersionList that both consume: per declared range it pins the lowest supported version exactly and adds the newest of every major the range spans, keyed by the bare major. Covering each major (not the raw range, which only resolves to the newest of the whole range) makes sure the floor major's latest is tested too. `*` collapses to the latest major, and an empty or unparseable entry throws instead of being skipped. * test: drive install script and withVersions from the shared resolver Both call sites now consume resolvePluginVersions, so the generated versions/ folders and the folders withVersions() iterates derive from one place and can no longer drift. The generator caps its mkdir/writeFile fan-out through the concurrency helper to avoid EMFILE. The resolver fills every in-between major on its own, so the lodash, ws, and mquery same-name externals that only re-stated their addHook ranges are dropped. Two peer-dependency anchors are added in their place: @apollo/server pins graphql so v5 does not resolve the 15.x that apollo-server v3 drags in, and knex installs the @vscode/sqlite3 fork its 1.x dialect requires.
…-install-concurrency-helper
…apped Expanding a declared range to bare-major keys made the top key resolve to the package.json pin regardless of the range's upper bound: microgateway-core `>=2.1 <=3.0.0` produced key `3`, which installs 3.3.7 — a version the instrumentation does not support — so traced operations emitted `web.request` instead of `microgateway.request`. The top key is now the declared range itself and in-between majors are keyed by a bounded `>=N.0.0 <N+1.0.0` range, so a version above the declared ceiling is never installed or tested.
(cherry picked from commit 4b9d78c)
…x add timeout (cherry picked from commit 7338306)
…ror survives loadSync (cherry picked from commit 19989f1)
…g CI (cherry picked from commit 072afc5)
…ient emits (cherry picked from commit d830524)
…pports (cherry picked from commit 5d52139)
Listeners the caller registers on `bulkLoad.getRowStream()` ran in whatever async context emitted the stream event, so the span active at registration was lost once the tracer moved to AsyncLocalStorage; `'finish'`/`'error'`/`'data'` handlers were traced under the wrong (or no) span. Each caller-registered listener is now bound to its registration context. tedious' own internal listeners attach before `getRowStream` returns, so only caller listeners are bound. The bulkload specs are adjusted for the majors the version-range expansion now exercises (the >=13 shards) and read the DBM comment from the executed query.
…9019 withVersions() and the install script each expanded a module's declared version ranges into the set of versions/<name>@<key> folders to test and install, and the two computations had drifted — a folder could be installed but never tested, or tested but never installed. A single resolvePluginVersions now drives both, so the installed set and the tested set cannot diverge. Per declared range the resolver pins the lowest supported version exactly, fills each in-between major with a bounded >=N.0.0 <N+1.0.0 key, and keeps the declared range itself as the top key. Keying the top by the range (not a bare major) is what keeps a capped range capped: microgateway-core >=2.1 <=3.0.0 resolves to 3.0.0, not the 3.3.7 a bare-major 3 key would pull in — a version the instrumentation does not support, which had it emitting web.request instead of microgateway.request. Generating the whole versions/ tree is thousands of mkdir/writeFile calls; an unbounded Promise.all over the tree exhausts file descriptors (EMFILE). A bounded-concurrency worker pool caps in-flight work, preserves input order, and stops scheduling once any worker fails. Expanding to every major surfaced real per-major gaps, fixed alongside: 1. restify runs the 4-6 and 10+ majors with async-only routing gated. 2. knex 1.x installs the @vscode/sqlite3 fork its dialect needs. 3. grpc's invalid.proto is proto2 so the required-field decode error survives loadSync. 4. hapi covers 16.x and 21+ and skips the EOL 19/20 majors that hang CI. 5. elasticsearch tolerates the util._extend deprecation the legacy client emits. 6. express-mongo-sanitize pins the <5 express folder it supports. 7. tedious BulkLoad row-stream listeners run in the caller's span, with bulkload specs adjusted for the >=13 shards. The resolver fills in-between majors on its own, so the lodash, ws, and mquery same-name externals that only re-stated their addHook ranges are dropped. Two peer-dependency anchors replace them: @apollo/server pins graphql so v5 does not resolve the 15.x apollo-server v3 drags in, and knex installs the @vscode/sqlite3 fork.
…9019 withVersions() and the install script each expanded a module's declared version ranges into the set of versions/<name>@<key> folders to test and install, and the two computations had drifted — a folder could be installed but never tested, or tested but never installed. A single resolvePluginVersions now drives both, so the installed set and the tested set cannot diverge. Per declared range the resolver pins the lowest supported version exactly, fills each in-between major with a bounded >=N.0.0 <N+1.0.0 key, and keeps the declared range itself as the top key. Keying the top by the range (not a bare major) is what keeps a capped range capped: microgateway-core >=2.1 <=3.0.0 resolves to 3.0.0, not the 3.3.7 a bare-major 3 key would pull in — a version the instrumentation does not support, which had it emitting web.request instead of microgateway.request. Generating the whole versions/ tree is thousands of mkdir/writeFile calls; an unbounded Promise.all over the tree exhausts file descriptors (EMFILE). A bounded-concurrency worker pool caps in-flight work, preserves input order, and stops scheduling once any worker fails. Expanding to every major surfaced real per-major gaps, fixed alongside: 1. restify runs the 4-6 and 10+ majors with async-only routing gated. 2. knex 1.x installs the @vscode/sqlite3 fork its dialect needs. 3. grpc's invalid.proto is proto2 so the required-field decode error survives loadSync. 4. hapi covers 16.x and 21+ and skips the EOL 19/20 majors that hang CI. 5. elasticsearch tolerates the util._extend deprecation the legacy client emits. 6. express-mongo-sanitize pins the <5 express folder it supports. 7. tedious BulkLoad row-stream listeners run in the caller's span, with bulkload specs adjusted for the >=13 shards. The resolver fills in-between majors on its own, so the lodash, ws, and mquery same-name externals that only re-stated their addHook ranges are dropped. Two peer-dependency anchors replace them: @apollo/server pins graphql so v5 does not resolve the 15.x apollo-server v3 drags in, and knex installs the @vscode/sqlite3 fork.
Key each expanded major by its bare major (`versions/mongodb@3`) instead of a bounded range (`versions/mongodb@>=3.0.0 <4.0.0`). The bare major reads cleanly as a folder name and covers each major's latest, including the floor major's, which the range form dropped. Follows the shared resolver from #9019. Widening the matrix to every major's latest surfaced several latent failures: 1. A bare-major key resolves to that major's newest version, so a range ending inside its top major overshoots: microgateway-core `>=2.1 <=3.0.0` keyed `3` installed 3.3.7 and the span came back `web.request` instead of `microgateway.request`. The top major keeps the declared range whenever it stops short of the major's ceiling; fully-spanned and lower majors stay bare. 2. `versions/ai@4` and `@langchain/core@0` resolve to versions that have no VCR cassette and would hit the live API (401). A central `brokenVersions` registry drops a matching resolved version and surfaces the reason as a pending test, each entry a stop-gap carrying a TODO. 3. A manifest carrying a `workspace:` protocol dependency was copied verbatim into a generated workspace, so yarn failed with "Couldn't find any versions for X that matches workspace:*". Fall back to the pinned compatible version. 4. The Apollo fetch-failure test gated the error span on `version > '2.3.0'`, a lexicographic compare that breaks once the key is bare (`'2' > '2.3.0'` is false). Compare the resolved version with `semver.gt`. 5. Single-digit keying renames folders that several specs hard-code by range (express, langchain, bedrock runtime, aws-sdk). The bedrock require threw after `agent.load` with no `agent.close`, leaving the Remote Config poll running and hanging the job to the 45-minute timeout; the others silently skipped suites. Point the requires at the renamed folders.
Key each expanded major by its bare major (`versions/mongodb@3`) instead of a bounded range (`versions/mongodb@>=3.0.0 <4.0.0`). The bare major reads cleanly as a folder name and covers each major's latest, including the floor major's, which the range form dropped. Follows the shared resolver from #9019. Widening the matrix to every major's latest surfaced several latent failures: 1. A bare-major key resolves to that major's newest version, so a range ending inside its top major overshoots: microgateway-core `>=2.1 <=3.0.0` keyed `3` installed 3.3.7 and the span came back `web.request` instead of `microgateway.request`. The top major keeps the declared range whenever it stops short of the major's ceiling; fully-spanned and lower majors stay bare. 2. `versions/ai@4` and `@langchain/core@0` resolve to versions that have no VCR cassette and would hit the live API (401). A central `brokenVersions` registry drops a matching resolved version and surfaces the reason as a pending test, each entry a stop-gap carrying a TODO. 3. A manifest carrying a `workspace:` protocol dependency was copied verbatim into a generated workspace, so yarn failed with "Couldn't find any versions for X that matches workspace:*". Fall back to the pinned compatible version. 4. The Apollo fetch-failure test gated the error span on `version > '2.3.0'`, a lexicographic compare that breaks once the key is bare (`'2' > '2.3.0'` is false). Compare the resolved version with `semver.gt`. 5. Single-digit keying renames folders that several specs hard-code by range (express, langchain, bedrock runtime, aws-sdk). The bedrock require threw after `agent.load` with no `agent.close`, leaving the Remote Config poll running and hanging the job to the 45-minute timeout; the others silently skipped suites. Point the requires at the renamed folders.
Key each expanded major by its bare major (`versions/mongodb@3`) instead of a bounded range (`versions/mongodb@>=3.0.0 <4.0.0`). The bare major reads cleanly as a folder name and covers each major's latest, including the floor major's, which the range form dropped. Follows the shared resolver from #9019. Widening the matrix to every major's latest surfaced several latent failures: 1. A bare-major key resolves to that major's newest version, so a range ending inside its top major overshoots: microgateway-core `>=2.1 <=3.0.0` keyed `3` installed 3.3.7 and the span came back `web.request` instead of `microgateway.request`. The top major keeps the declared range whenever it stops short of the major's ceiling; fully-spanned and lower majors stay bare. 2. `versions/ai@4` and `@langchain/core@0` resolve to versions that have no VCR cassette and would hit the live API (401). A central `brokenVersions` registry drops a matching resolved version and surfaces the reason as a pending test, each entry a stop-gap carrying a TODO. 3. A manifest carrying a `workspace:` protocol dependency was copied verbatim into a generated workspace, so yarn failed with "Couldn't find any versions for X that matches workspace:*". Fall back to the pinned compatible version. 4. The Apollo fetch-failure test gated the error span on `version > '2.3.0'`, a lexicographic compare that breaks once the key is bare (`'2' > '2.3.0'` is false). Compare the resolved version with `semver.gt`. 5. Single-digit keying renames folders that several specs hard-code by range (express, langchain, bedrock runtime, aws-sdk). The bedrock require threw after `agent.load` with no `agent.close`, leaving the Remote Config poll running and hanging the job to the 45-minute timeout; the others silently skipped suites. Point the requires at the renamed folders.
Summary
withVersions()and the install script each expanded a module's declaredversion ranges into the set of
versions/<name>@<key>folders to test andinstall, and the two computations had drifted — a folder could be installed but
never tested, or tested but never installed. A single
resolvePluginVersionsnow drives both, so the installed set and the tested set cannot diverge.
Per declared range the resolver pins the lowest supported version exactly, fills
each in-between major with a bounded
>=N.0.0 <N+1.0.0key, and keeps thedeclared range itself as the top key. Keying the top by the range (not a bare
major) is what keeps a capped range capped:
microgateway-core >=2.1 <=3.0.0resolves to 3.0.0, not the 3.3.7 a bare-major
3key would pull in — a versionthe instrumentation does not support, which had it emitting
web.requestinstead of
microgateway.request.Generating the whole
versions/tree is thousands ofmkdir/writeFilecalls;an unbounded
Promise.allover the tree exhausts file descriptors (EMFILE).A bounded-concurrency worker pool caps in-flight work, preserves input order, and
stops scheduling once any worker fails.
test:scriptsruns its spec in CI.Expanding to every major surfaced real per-major gaps, fixed alongside:
@vscode/sqlite3fork its dialect needs.invalid.protois proto2 so the required-field decode error survivesloadSync.util._extenddeprecation the legacy client emits.<5express folder it supports.The resolver fills in-between majors on its own, so the lodash, ws, and mquery
same-name externals that only re-stated their addHook ranges are dropped. Two
peer-dependency anchors replace them:
@apollo/serverpins graphql so v5 doesnot resolve the 15.x apollo-server v3 drags in, and knex installs the
@vscode/sqlite3fork.Test plan
yarn test:scripts(resolver + concurrency unit specs).