feat(search): consumer-field contract test + index mapping health check#28751
feat(search): consumer-field contract test + index mapping health check#28751pmbrull wants to merge 3 commits into
Conversation
Guard the denormalized search-index fields that RBAC, Data Quality, Incident Manager, Lineage, and Data Insights query (tags.tagFQN, tier, certification, owners, domains, fqnParts, testCaseStatus, ...). Renaming, retyping, or dropping one silently breaks those consumers with no compile- or boot-time failure. - SearchConsumerFields: single source of truth for the consumer contract. - SearchConsumerFieldContractTest: fails CI on a type change or a dropped field in any mapping (across all 4 languages), naming the affected consumers. - "Index Mapping Consistency" StepValidation on /system/validate: non-blocking health check that reads the live deployed mapping and warns "reindex required" when a core data-asset index is missing these fields (e.g. stale after upgrade). Adds a read-only getIndexFieldNames to the SearchClient (Elasticsearch + OpenSearch). - Fix jp/topic mapping missing top-level `domains` (found by the new test) — JP-locale topic search had lost domain-based RBAC/DQ filtering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| private StepValidation getMappingConsistencyValidation() { | ||
| StepValidation step = | ||
| new StepValidation().withDescription(ValidationStepDescription.SEARCH_MAPPING.key); | ||
| SearchRepository searchRepository = Entity.getSearchRepository(); | ||
| StepValidation result; | ||
| if (searchRepository.getSearchClient().isClientAvailable()) { | ||
| List<String> inconsistent = findIndexesWithMissingConsumerFields(searchRepository); | ||
| result = | ||
| step.withPassed(inconsistent.isEmpty()) | ||
| .withMessage(buildMappingConsistencyMessage(inconsistent)); | ||
| } else { | ||
| result = | ||
| step.withPassed(Boolean.TRUE).withMessage("Skipped: search instance is not reachable."); | ||
| } | ||
| return result; |
There was a problem hiding this comment.
💡 Performance: validateSystem issues up to 10 uncached getMapping round-trips
getMappingConsistencyValidation is invoked on every /system/validate call and performs one synchronous getMapping network round-trip per entry in CANARY_DATA_ASSET_ENTITIES (10 indexes), with no caching. This is acceptable for a manually triggered admin endpoint, but if /system/validate is ever polled by monitoring/health tooling the added latency and ES/OS load become noticeable. Consider a short-lived cache of the result (similar to the existing HEALTH_CHECK_CACHE_MS pattern in the search clients) or documenting that this endpoint is admin-only/low-frequency.
Was this helpful? React with 👍 / 👎
…ract Index a document into the real en/jp/ru/zh index mapping for topic and test_case, then run the actual search/filter/aggregation each feature uses (tag/tier/certification/domain term filters, owners nested RBAC query, testCaseResult.testCaseStatus aggregation, fqnParts term) and assert it returns the document. A failure reads as a broken feature in a specific language, not "index is missing a mapping" — and would have caught the jp/topic domains drop. Runs against a real OpenSearch testcontainer. Text analyzers are stripped before index creation (the consumer fields are keyword/nested and analyzer-independent) so each language index is creatable without analysis plugins while the real field structure is still validated per language. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…zers 30 of 55 jp index mappings referenced an analyzer name the file does not define: an incomplete om_analyzer -> om_analyzer_jp rename left field-level analyzer / search_analyzer references pointing at the other name. OpenSearch/Elasticsearch reject index creation with "analyzer [...] has not been configured", so those jp indexes could not be built at all — independent of the analysis-kuromoji plugin requirement (a separate deployment concern for jp). Repoint each dangling reference to the analyzer that file actually defines: behavior-preserving, only analyzer reference strings change (no field, type, or analyzer definition is touched). Files that define both analyzers are left as-is. Surfaced by SearchConsumerFieldBehaviorIT. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| "name": { | ||
| "type": "text", | ||
| "analyzer": "om_analyzer_jp", | ||
| "analyzer": "om_analyzer", |
There was a problem hiding this comment.
⚠️ Edge Case: jp/api_collection repointed to English analyzer, not kuromoji
This commit repoints analyzer references the right way for almost every jp index: those files define om_analyzer_jp (kuromoji) in settings.analysis.analyzer but had dangling field references to om_analyzer, so they were correctly changed to om_analyzer_jp. jp/api_collection_index_mapping.json is the lone exception — it went the opposite direction (om_analyzer_jp -> om_analyzer) on name, displayName, and description.
Root cause: unlike every other jp mapping, api_collection's settings block was never localized — it still defines om_analyzer with the English kstem stemmer (lines 27-56) rather than om_analyzer_jp with the kuromoji tokenizer/filters that topic, container, glossary, etc. define. Because the only analyzer actually declared in this file is om_analyzer, the fix made the field references consistent with the (un-localized) settings rather than fixing the settings.
Impact: the dangling-reference fix is correct (referencing an undefined om_analyzer_jp would have failed index creation), but the result is that JP full-text search over API Collections (name/displayName/description) silently uses English tokenization instead of Japanese — inconsistent with the rest of the jp locale. The denormalized consumer fields (keyword/nested) are unaffected, so RBAC/DQ still work; this is a search-quality regression for Japanese text on this one index.
Suggested fix: localize api_collection's settings to define om_analyzer_jp (kuromoji) matching the other jp indexes, and keep the three field references at om_analyzer_jp rather than downgrading them to om_analyzer.
Was this helpful? React with 👍 / 👎
Code Review
|
| Compact |
|
Was this helpful? React with 👍 / 👎 | Gitar
Describe your changes:
No tracking issue yet — opened from a search-indexing reliability audit. Please link an issue before this leaves draft.
Search denormalizes a set of fields (
tags.tagFQN,tier,certification,owners,domains,fqnParts,testCaseResult.testCaseStatus, …) into every entity document, and RBAC, Data Quality, Incident Manager, Lineage, and Data Insights query them directly — so a mapping change that renames, retypes, or drops one breaks those features silently, with no compile- or boot-time failure. This PR adds two guards against that, plus the bug the guards immediately surfaced.Type of change:
High-level design:
SearchConsumerFields— one source of truth for the consumer contract (denormalized leaf fields + required type, and the core data-asset canary set), referenced by both guards so the contract lives in one place.SearchConsumerFieldContractTest(CI) — over every entity mapping × 4 languages: (1) the denormalized leaf fields keep theirkeywordtype wherever present, and (2) core data-asset indexes expose the full denormalized set. Failures name the affected consumer.StepValidationadded toSystemRepository.validateSystem()(the existing/system/validateSearch Instance check). It reads the live deployed mapping (new read-onlygetIndexFieldNamesonSearchClient→ Elasticsearch/OpenSearch index managers) and warns "reindex required" when a deployed core index is missing these fields (e.g. left stale after an upgrade). Chosen over a boot-time fail-fast — which would block the very reindex needed to fix it — and over the hash version-table, which is CLI-only-populated and would false-positive on UI reindexes.jp/topicindex mapping was missing top-leveldomains(the new test caught it), so JP-locale topic search had lost domain-based RBAC and DQ/Incident filtering. Added to matchen/ru/zh.Tests:
Use cases covered
/system/validatereports a non-blocking warning when a deployed core data-asset index is missing denormalized fields.Unit tests
SearchConsumerFieldContractTest(2) andSystemRepositoryMappingConsistencyTest(4); existingIndexMappingNestedFieldConsistencyTeststill green. All 9 pass;mvn -pl openmetadata-service spotless:checkclean.Backend integration tests
validateSystemchange is covered by the unit test.Ingestion integration tests
Playwright (UI) tests
Manual testing performed
mvn -pl openmetadata-service test -Dtest='SearchConsumerFieldContractTest,SystemRepositoryMappingConsistencyTest,IndexMappingNestedFieldConsistencyTest'→ 9/9 pass.mvn -pl openmetadata-service spotless:check→ clean.UI screen recording / screenshots:
Not applicable.
Checklist:
Fixes <issue-number>: <short explanation>Fixes #<issue-number>above.