Skip to content

feat: add a search index page to the admin dashboard - #2121

Merged
netomi merged 3 commits into
mainfrom
feat/admin-search-index
Sep 1, 2026
Merged

netomi merged 3 commits into
mainfrom
feat/admin-search-index

Conversation

@netomi

@netomi netomi commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

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 a ManageSearch icon.

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:

State What it says
counts agree Every active extension is indexed
index short N active extensions are missing from the index and cannot be found by searching
index long The index holds N more entries than there are active extensions, so it lists some that no longer exist
no index The index does not exist. Searching returns nothing until it is built
database engine Searches are answered from the database, so there is no index to report on or rebuild
search disabled Searching is disabled on this registry

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 with repositories.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. indexedDocuments is omitted when there is no index to have counted, rather than serialised as 0.

Tests

Server: three AdminAPITest cases — 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 test passed while yarn build failed: AdminService is 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

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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-index page (lazy-loaded + nav entry) with stats display and rebuild action.
  • Server: introduces SearchIndexStats and GET /admin/search-index returning SearchIndexJson derived from the active search engine.
  • Tests + types: adds frontend unit tests and extends the web UI service/types; adds server AdminAPITest coverage.

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.

netomi and others added 2 commits September 1, 2026 22:44
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>
@netomi
netomi merged commit ea96415 into main Sep 1, 2026
5 checks passed
@netomi
netomi deleted the feat/admin-search-index branch September 1, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants