Add language aggregations for Zoekt code search (backend)

What does this MR do and why?

Issue: #392882

Split from !243585 — this is MR 1 of 2 (backend). See the frontend follow-up in the description of this MR once it's opened.

Adds the backend for Zoekt language aggregations in code search, gated behind the zoekt_language_aggregations feature flag (default off). Nothing in the UI changes until the frontend MR lands.

Why split

Per reviewer guidance, shipping new GraphQL fields together with the frontend that requests them creates a Self-Managed upgrade window where the frontend asks for fields the backend doesn't yet know about, producing GraphQL errors that can make the app unresponsive. Splitting backend-first eliminates that window.

Backend changes

  • New language filter argument on the GraphQL blobSearch resolver so callers can narrow Zoekt results to specific detected languages.
  • Threads the language filter through Search::Zoekt::CodeQueryBuilder, MultiMatch, SearchRequest, and SearchResults.
  • Adds Search::Zoekt::AggregationCache: a standalone Redis cache for language-bucket tallies, keyed independently of pagination and of the language filter itself so bucket counts stay stable across faceted ticks. Includes search_mode in the fingerprint so regex and exact tallies don't collide.
  • Exposes zoekt_language_aggregations_enabled? on SearchServicePresenter, wired through app/views/search/show.html.haml so the frontend can read the flag from gon once the frontend MR lands.

Frontend follow-up

The frontend MR (to be opened after this one) consumes the new language argument behind @gl_introduced(version: "18.3.0") on the GraphQL query field, so older Self-Managed instances that don't yet have this backend deployed skip the field gracefully instead of erroring.

Note on the diff

doc/api/graphql/reference/_index.md and public/-/graphql/introspection_result.json contain a couple of lines unrelated to this feature (SecretsManagementAction.READ_VALUE) — those are the result of regenerating the derived GraphQL docs against current master, which merged a security fix that added that enum value. Regeneration is required by the pre-push check (graphql_introspection_check, graphql_docs); leaving them stale isn't an option.

MR acceptance checklist

  • Changes are behind a feature flag: zoekt_language_aggregations
  • Test plan covered by new specs under ee/spec/lib/search/zoekt/*_spec.rb and ee/spec/requests/api/graphql/search/blob_search_spec.rb
Edited by Ravi Kumar

Merge request reports

Loading