fix: cap pre-release versions returned by extensionQuery - #2062
Conversation
extensionQuery (vscode/gallery/extensionquery) fetches every active version of every requested extension when FLAG_INCLUDE_VERSIONS or FLAG_INCLUDE_VERSION_PROPERTIES is set. For an extension whose pre-release channel publishes one build per commit, that history can grow into the thousands, making the query and response needlessly expensive. Regular releases are left untouched, but active pre-release versions are now capped to the most recent N per extension (combined across all of its target platforms), ranked by the same semver-based ordering ExtensionVersion.SORT_COMPARATOR uses for "latest" - so the true latest pre-release (rank #1) is never dropped by the cap. The cap is a plain method parameter threaded through LocalVSCodeService -> RepositoryService -> ExtensionVersionJooqRepository, configured via ovsx.extension-query.max-pre-release-versions (default 100). A negative value (e.g. -1) disables the cap entirely, matching the "negative means unlimited" convention already used for ovsx.data.mirror.requests-per-second. Adds coverage in ExtensionVersionJooqRepositoryTest for: capping while leaving stable releases untouched, capping across target platforms combined rather than per platform, the target-platform filter being applied after the cap, honouring a caller-supplied limit, and disabling the cap with a negative value. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a configurable cap on how many active pre-release channel versions are returned by the VS Code extensionQuery path, to prevent queries/responses from growing unbounded when pre-release channels publish very frequently, while leaving stable releases unaffected.
Changes:
- Thread a
maxPreReleaseVersionsparameter throughLocalVSCodeService -> RepositoryService -> ExtensionVersionJooqRepository. - Implement repository-side filtering to limit active pre-release versions per extension (cross-platform combined), with a negative value disabling the cap.
- Add/adjust tests and mocks to cover the new behavior and updated method signature.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java | Adds configurable ovsx.extension-query.max-pre-release-versions and passes it into repository query. |
| server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java | Extends findActiveExtensionVersions to accept maxPreReleaseVersions. |
| server/src/main/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepository.java | Adds SQL-side pre-release capping logic. |
| server/src/test/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepositoryTest.java | Adds coverage for pre-release capping semantics (stable untouched, cross-platform cap, negative disables). |
| server/src/test/java/org/eclipse/openvsx/repositories/RepositoryServiceSmokeTest.java | Updates smoke test call site for new method signature. |
| server/src/test/java/org/eclipse/openvsx/adapter/LocalVSCodeServiceTest.java | Updates mocks for new repository method signature. |
| server/src/test/java/org/eclipse/openvsx/adapter/VSCodeAPITest.java | Updates mocks for new repository method signature. |
| server/src/test/java/org/eclipse/openvsx/RegistryAPITest.java | Updates mocks for new repository method signature. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Addresses a review comment on this PR: isAmongLatestPreReleases ranked pre-releases by (semver_major, semver_minor, semver_patch) alone. Two rows tied on that triple - the normal case, not an edge case, since the same version published across several target platforms shares one (major, minor, patch) by construction, and a pre-release channel that republishes without bumping semver ties too - neither outranks the other, so neither counts against the cap. Unbounded ties meant the cap could fail to cap at all for exactly the "one build per commit" pre-release channel this PR targets. Fall back to timestamp, matching ExtensionVersion.SORT_COMPARATOR and every DB sort index in this class, which already resolve same-semver ties that way. Add id as a final tiebreaker so the comparison is a strict total order, guaranteeing the cap keeps exactly min(limit, total) rows rather than "at least". Adds a regression test with 105 pre-release versions sharing one version string (only target platform and timestamp differ) that fails on the prior comparison (105 returned, uncapped) and passes with the fix (capped to 100, most recent one kept). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Make the pre-release cap opt-in rather than on-by-default: -1 (disabled) preserves the exact pre-existing, uncapped behaviour out of the box. Operators who want the cap set ovsx.extension-query.max-pre-release-versions explicitly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Suppressed comments (2)
server/src/main/java/org/eclipse/openvsx/adapter/LocalVSCodeService.java:99
- The PR description says
ovsx.extension-query.max-pre-release-versionsdefaults to 100, but the code currently defaults to-1(unlimited). This is a behavioral mismatch: with-1the cap is disabled unless operators opt in, which contradicts the stated default and the PR’s stated purpose of reducing expensive queries/responses by default.
// fetches per extensionQuery request; regular releases are never capped. A negative value
// (e.g. the -1 default) disables the cap entirely, preserving the pre-existing unbounded
// behaviour unless an operator opts into capping.
@Value("${ovsx.extension-query.max-pre-release-versions:-1}")
int maxPreReleaseVersions;
server/src/test/java/org/eclipse/openvsx/repositories/ExtensionVersionJooqRepositoryTest.java:222
- This comment says the cross-platform cap is applied before the “win32-x64 filter below”, but the test actually requests
linux-x64only. The wording is misleading when reading the test intent.
// 99 higher-semver win32 pre-releases crowd out all but the newest of the 2 linux
// pre-releases from the cross-platform top-100 cap, before the win32-x64 filter below is
// even applied - so requesting linux-x64 only can see fewer than 100 versions even though
// more than 100 exist for the extension overall.
What
extensionQuery(/vscode/gallery/extensionquery) fetches every active version of every requested extension whenFLAG_INCLUDE_VERSIONSorFLAG_INCLUDE_VERSION_PROPERTIESis set. For an extension whose pre-release channel publishes one build per commit, that history can grow into the thousands, making the query and the response needlessly expensive.Regular releases are left completely untouched. Active pre-release versions are now capped to the most recent N per extension (combined across all of its target platforms), ranked by the same semver-based ordering
ExtensionVersion.SORT_COMPARATORuses for "latest" - so the true latest pre-release (rank #1) can never be dropped by the cap, and downstream "latest version" computations stay correct.How
The cap is a plain method parameter threaded through:
configured on
LocalVSCodeServiceviaovsx.extension-query.max-pre-release-versions(default100). A negative value (e.g.-1) disables the cap entirely, matching the "negative means unlimited" convention already used forovsx.data.mirror.requests-per-second.Implementation detail: the SQL adds a correlated-subquery condition (
EXTENSION_VERSION.PRE_RELEASE.isFalse().or(isAmongLatestPreReleases(limit))) rather than a window-function/derived-table rewrite, since the existing flat query's generictoExtensionVersionrow mapper can't safely be reused once wrapped in a derived table (duplicateNAMESPACE.ID/EXTENSION.ID/EXTENSION_VERSION.IDcolumn names collide once re-selected).Testing
ExtensionVersionJooqRepositoryTestgains coverage for:Existing call sites/mocks (
LocalVSCodeServiceTest,VSCodeAPITest,RegistryAPITest,RepositoryServiceSmokeTest) updated for the new parameter.