Fix silent data loss in Advanced Search routing for >128 root_ancestor_ids

What does this MR do and why?

When searching with more than 128 root ancestor IDs, the routing logic in ee/lib/elastic/latest/routing.rb emits { routing: [] } which serializes to routing= (empty string). Elasticsearch interprets this as 'search zero shards', returning 0 hits with HTTP 200 — silent data loss that looks like a successful empty result.

Root cause: The root_ancestor_ids branch lacked the blank guard that the project_ids branch already has. When build_routing returns [] for >128 IDs, it was returned directly as { routing: [] } instead of falling back to an unrouted search.

Fix: Add return {} if routing.blank? to the root_ancestor_ids branch, matching the existing pattern in the project_ids branch. When root ancestor count exceeds 128, the search now degrades gracefully to an unrouted (all-shard) search returning all results.

References

Screenshots or screen recordings

N/A — backend-only change, no UI impact.

Before After
routing_options({ root_ancestor_ids: (1..129).to_a }) returns { routing: [] } → ES searches zero shards → 0 hits routing_options({ root_ancestor_ids: (1..129).to_a }) returns {} → ES searches all shards → correct results

How to set up and validate locally

  1. Open a Rails console
  2. Run:
    proxy = Elastic::Latest::ApplicationClassProxy.new(Issue)
    # Before fix: returns { routing: [] } — broken
    # After fix: returns {} — correct fallback to all-shard search
    proxy.routing_options({ root_ancestor_ids: (1..129).to_a })
  3. Verify it returns {} (empty hash, no routing key)
  4. Verify ≤128 IDs still return the correct routing string:
    proxy.routing_options({ root_ancestor_ids: [1, 2, 3] })
    # => { routing: 'group_1,group_2,group_3' }

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports

Loading