Repository navigation
feat: add a search index page to the admin dashboard - #2121
Merged
Merged
Conversation
Nothing reported on the search index. Whether it held every extension, a few, or none could only be inferred by searching for something and noticing it missing - which looks exactly the same as the extension not existing. The rebuild existed as an endpoint with nothing to call it. The page leads with the comparison that matters: how many extensions the index holds against how many it is built from. It names the case rather than leaving the subtraction to the reader - entries missing, more entries than extensions, no index at all, searches answered from the database, or searching switched off - and then offers the rebuild. Server side, SearchUtilService reports on whichever engine is actually answering searches; the database engine has no index and says so instead of reporting zero documents, which would read as a broken index rather than a different one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an admin-dashboard page and server API to make the search index state observable (indexed vs active extension counts) and to trigger a rebuild from the UI, addressing the “silent drift/empty-looking search” problem described in the PR.
Changes:
- Web UI: adds
/admin-dashboard/search-indexpage (lazy-loaded + nav entry) with stats display and rebuild action. - Server: introduces
SearchIndexStatsandGET /admin/search-indexreturningSearchIndexJsonderived from the active search engine. - Tests + types: adds frontend unit tests and extends the web UI service/types; adds server
AdminAPITestcoverage.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| webui/test/unit/pages/admin-dashboard/search-index.spec.tsx | Adds unit tests for all reported search-index states and rebuild refetch. |
| webui/src/pages/admin-dashboard/search-index/use-search-index.ts | Adds React Query hooks for fetching stats and triggering index update. |
| webui/src/pages/admin-dashboard/search-index/search-index.tsx | Implements the new admin UI page (health messaging, stats, rebuild UI). |
| webui/src/pages/admin-dashboard/admin-dashboard.tsx | Adds lazy-loaded route + nav entry for “Search Index”. |
| webui/src/pages/admin-dashboard/admin-dashboard-routes.ts | Defines SEARCH_INDEX route constant. |
| webui/src/extension-registry-types.ts | Adds SearchIndex DTO type consumed by the UI. |
| webui/src/extension-registry-service.ts | Extends AdminService contract + implementation with getSearchIndex/updateSearchIndex. |
| webui/CHANGELOG.md | Documents the new admin dashboard page. |
| server/src/test/java/org/eclipse/openvsx/admin/AdminAPITest.java | Adds endpoint tests for admin stats + field omission + 403 for non-admin. |
| server/src/main/java/org/eclipse/openvsx/search/SearchUtilService.java | Routes stats to the active engine and pairs with active-extension count. |
| server/src/main/java/org/eclipse/openvsx/search/SearchIndexStats.java | Adds record describing index/search-engine state for reporting. |
| server/src/main/java/org/eclipse/openvsx/search/ElasticSearchService.java | Adds getIndexStats() (index existence, document count, max result window). |
| server/src/main/java/org/eclipse/openvsx/json/SearchIndexJson.java | Adds JSON model (NON_NULL) for admin dashboard stats response. |
| server/src/main/java/org/eclipse/openvsx/admin/AdminAPI.java | Adds GET /admin/search-index endpoint returning SearchIndexJson. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The page told you searches were answered from the database and that there was no index to rebuild, then offered the button anyway. Pressing it would have reported "Rebuilt the search index" without rebuilding anything: DatabaseSearchService.updateSearchIndex only evicts a cache. The rebuild is offered for elasticsearch only, and only while searching is enabled. A missing index keeps it, since building one is exactly the remedy there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Hiding the button stops the dashboard offering it, but the endpoint is reachable regardless, and SearchUtilService falls back to elasticsearch when nothing is enabled - so a rebuild with the database engine, or with searching switched off, would drive an engine this registry is not using or report having rebuilt an index that does not exist. Also records the third value of SearchIndexStats.implementation in its javadoc, which listed only two of the three. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nothing reported on the search index. Whether it held every extension, a few, or none could only be inferred by searching for something and noticing it missing — which looks exactly the same as the extension not existing. The rebuild already existed as an endpoint (
POST /admin/update-search-index) with nothing in the UI to call it.The page
/admin-dashboard/search-index, lazy-loaded, in the nav under aManageSearchicon.It leads with the comparison rather than a table of numbers: how many extensions the index holds against how many it is built from. That is deliberate — an index that has quietly lost entries answers searches perfectly well, just with nothing in them, and no single number distinguishes that from an empty registry. The page names the case instead of leaving the subtraction to the reader:
Then the statistics — engine, indexed extensions, active extensions, max result window — and the rebuild, which notes that searching returns incomplete results while it runs.
Server
SearchIndexStats— a record of what can be said about the index without searching as a user would.ElasticSearchService.getIndexStats()counts the index and pairs it withrepositories.countActiveExtensions(), the number the index is built from.SearchUtilService.getIndexStats()routes to whichever engine is live. The database engine reports no index rather than zero documents, since zero would read as a broken index rather than a different one.GET /admin/search-index→SearchIndexJson, alongside the existing update endpoint.indexedDocumentsis omitted when there is no index to have counted, rather than serialised as0.Tests
Server: three
AdminAPITestcases — full statistics, the no-index case asserting the field is absent, and non-admin → 403. 1019 server tests pass.Web UI: eight cases covering every state in the table above plus the rebuild refetching the statistics. Fail-first checked — stubbing the drift calculation to zero turns both drift cases red. 246 webui tests pass, lint and build clean, changelog entry added.
Worth knowing
yarn testpassed whileyarn buildfailed:AdminServiceis an interface declared separately from its implementation, and the tests mock it, so the two new methods were missing from the contract without any test noticing. Only the type check caught it. Anything adding a service method here should build, not just test.Open question
The rebuild is one click, no confirmation. It is disruptive while it runs, but it is also the remedy when the index is broken, so a confirmation dialog seemed like friction in the wrong place. Easy to add if you would rather have it.
🤖 Generated with Claude Code