Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
83b803c
Restore live index settings on per-entity distributed-promote path
harshach May 4, 2026
ba952d9
Wire jobData into per-entity reindex promotion handler
harshach May 4, 2026
80f01f6
Add regression test for live serving settings on per-entity promote
harshach May 5, 2026
c373592
Expand unit coverage around the per-entity promotion contract
harshach May 5, 2026
20e1cd4
Add integration test for live settings restoration after alias promotion
harshach May 5, 2026
a977032
Address PR review: harden settings revert + lock InOrder + drop redun…
harshach May 5, 2026
a2a2b4a
Drop verbose explanatory comments from promote-path edits
harshach May 5, 2026
f40a21b
Close Rest5Client in IT _settings helper
harshach May 5, 2026
4775e90
Tighten SearchIndexAliasPromotionIT against false-positive runs
harshach May 5, 2026
2af5827
Harden alias promotion: defer canonical delete, hard-fail on empty al…
harshach May 5, 2026
4654158
Consolidate finalizeReindex and promoteEntityIndex into one core path
harshach May 5, 2026
9a7fa49
Address PR review: post-state checks, FAILED listener, hermetic IT, I…
harshach May 6, 2026
8b4d1a8
Wrap post-state checks: indexExists / getAliases throws no longer escape
harshach May 6, 2026
2580597
Address Copilot review 4232747647: positive-evidence dataLoss, hermet…
harshach May 6, 2026
0351078
Merge branch 'main' into harshach/search-alias-promote
harshach May 6, 2026
30774c7
Wait for restore-triggered run to settle in SearchIndexAliasPromotionIT
harshach May 6, 2026
232d195
Fix AppsResourceIT.waitForAppJobCompletion case mismatch and timeout
harshach May 6, 2026
22717f5
Merge branch 'main' into harshach/search-alias-promote
mohityadav766 May 6, 2026
98b9871
Merge remote-tracking branch 'origin/main' into harshach/search-alias…
harshach May 6, 2026
aee61f2
Merge branch 'harshach/search-alias-promote' of github.com:open-metad…
harshach May 6, 2026
64a385a
Run SearchIndexAliasPromotionIT in the sequential bucket
harshach May 6, 2026
810ed16
Address Copilot PR review 4233452655
harshach May 6, 2026
cf18270
Remove SearchIndexAliasPromotionIT in favor of unit test coverage
harshach May 6, 2026
7d7e5db
Address Copilot PR review 4236718653
harshach May 6, 2026
bb973d8
Fix per-entity promote when canonical is an alias, not a concrete index
harshach May 6, 2026
0164cd8
Add ALIAS_PROMOTE_BEGIN diagnostic log per entity
harshach May 6, 2026
d80e44b
Drop heavy alias-promotion refactor; rely on PR #27930 fix already in…
harshach May 6, 2026
3e0d7ca
Merge remote-tracking branch 'origin/main' into harshach/search-alias…
harshach May 6, 2026
25240ec
Skip delete-by-alias-name when canonical is currently an alias
harshach May 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,17 @@ private void initializeEntityTracker(UUID jobId, boolean recreateIndex) {
// Set up per-entity promotion callback if recreating indices
if (recreateIndex && recreateContext != null) {
this.recreateIndexHandler = Entity.getSearchRepository().createReindexHandler();
// Wire jobData into the handler so applyLiveServingSettings (in
// DefaultRecreateHandler.promoteEntityIndex) can resolve the configured live + bulk
// index settings. Without this, jobData is null on the handler instance the per-entity
// callback uses, buildRevertJson returns null, and the bulk-build overrides
// (refresh_interval=-1, replicas=0, async translog) silently become the live settings.
if (recreateIndexHandler
instanceof org.openmetadata.service.search.DefaultRecreateHandler defaultHandler
&& currentJob != null
&& currentJob.getJobConfiguration() != null) {
defaultHandler.withJobData(currentJob.getJobConfiguration());
Comment thread
harshach marked this conversation as resolved.
Outdated
}
entityTracker.setOnEntityComplete(this::promoteEntityIndex);
LOG.info(
"Per-entity promotion callback SET for job {} (recreateIndex={}, recreateContext entities={})",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,15 @@ public void promoteEntityIndex(EntityReindexContext context, boolean reindexSucc
return;
}

// Restore live serving settings on the staged index before alias swap. The bulk-build
// overrides (refresh=-1, replicas=0, async translog) must NOT survive into live serving —
// otherwise live writes after promotion are buffered indefinitely and only become
// searchable on a manual _refresh, which surfaces as the "create-then-search returns
// nothing until reindex" symptom on knowledge pages. This mirrors the call in
// finalizeReindex; the per-entity distributed promotion path was missing it.
applyLiveServingSettings(searchClient, stagedIndex, entityType);
maybeForceMerge(searchClient, stagedIndex, entityType);
Comment thread
gitar-bot[bot] marked this conversation as resolved.
Outdated

// Always clear staged-index routing on the way out — see the rationale in finalizeReindex.
try {
Set<String> aliasesToAttach =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
Expand All @@ -24,9 +25,12 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration;
import org.openmetadata.schema.system.BulkIndexOverrides;
import org.openmetadata.schema.system.EventPublisherJob;
import org.openmetadata.search.IndexMapping;
import org.openmetadata.service.Entity;
import org.openmetadata.service.apps.bundles.searchIndex.ReindexingMetrics;
Expand Down Expand Up @@ -440,6 +444,59 @@ void testPromoteEntityIndexRecordsPromotionFailure() {

verify(metrics).recordPromotionFailure("table");
}

@Test
@DisplayName("Should restore live serving settings on staged index before alias swap")
void testPromoteEntityIndexAppliesLiveServingSettingsBeforeSwap() {
AliasState aliasState = new AliasState();
aliasState.put("table_search_index_rebuild_old", Set.of("table"));
aliasState.put("table_search_index_rebuild_new", new HashSet<>());

SearchClient client = aliasState.toMock();
SearchRepository repo = mock(SearchRepository.class);
when(repo.getSearchClient()).thenReturn(client);
when(repo.getClusterAlias()).thenReturn("");
when(repo.getIndexMapping("table"))
.thenReturn(
IndexMapping.builder()
.indexName("table_search_index")
.alias("table")
.parentAliases(List.of("all"))
.childAliases(List.of())
.build());

EventPublisherJob jobData =
new EventPublisherJob()
.withBulkIndexSettings(
new BulkIndexOverrides()
.withNumberOfReplicas(0)
.withRefreshInterval("-1")
.withTranslogDurability(BulkIndexOverrides.TranslogDurability.ASYNC)
.withTranslogSyncInterval("30s"));

try (MockedStatic<Entity> entityMock = mockStatic(Entity.class)) {
entityMock.when(Entity::getSearchRepository).thenReturn(repo);

EntityReindexContext context =
EntityReindexContext.builder()
.entityType("table")
.canonicalIndex("table_search_index")
.stagedIndex("table_search_index_rebuild_new")
.build();

new DefaultRecreateHandler().withJobData(jobData).promoteEntityIndex(context, true);
}

ArgumentCaptor<String> body = ArgumentCaptor.forClass(String.class);
verify(client).updateIndexSettings(eq("table_search_index_rebuild_new"), body.capture());
String json = body.getValue();
assertTrue(json.contains("\"refresh_interval\":\"1s\""), json);
assertTrue(json.contains("\"number_of_replicas\":1"), json);
assertTrue(json.contains("\"durability\":\"request\""), json);
assertTrue(
aliasState.indexAliases.get("table_search_index_rebuild_new").contains("table"),
"alias swap should still happen after settings revert");
Comment thread
harshach marked this conversation as resolved.
Outdated
}
}

@Nested
Expand Down
Loading