Skip to content

Commit 9f13eac

Browse files
committed
Set acking timeout to 0 on dynamic mapping update (#31140)
As acking can fail for any reason (unrelated node being too slow, node disconnecting), it should not be required for acking to succeed in order for index requests with dynamic mapping updates to successfully complete. Relates to #30672 and Closes #30844
1 parent 8765a31 commit 9f13eac

File tree

4 files changed

+55
-6
lines changed

4 files changed

+55
-6
lines changed

server/src/main/java/org/elasticsearch/cluster/action/index/MappingUpdatedAction.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.elasticsearch.cluster.action.index;
2121

22-
import org.elasticsearch.ElasticsearchTimeoutException;
2322
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder;
2423
import org.elasticsearch.client.Client;
2524
import org.elasticsearch.client.IndicesAdminClient;
@@ -67,7 +66,7 @@ private PutMappingRequestBuilder updateMappingRequest(Index index, String type,
6766
throw new IllegalArgumentException("_default_ mapping should not be updated");
6867
}
6968
return client.preparePutMapping().setConcreteIndex(index).setType(type).setSource(mappingUpdate.toString(), XContentType.JSON)
70-
.setMasterNodeTimeout(timeout).setTimeout(timeout);
69+
.setMasterNodeTimeout(timeout).setTimeout(TimeValue.ZERO);
7170
}
7271

7372
/**
@@ -84,8 +83,6 @@ public void updateMappingOnMaster(Index index, String type, Mapping mappingUpdat
8483
* been applied to the master node and propagated to data nodes.
8584
*/
8685
public void updateMappingOnMaster(Index index, String type, Mapping mappingUpdate, TimeValue timeout) {
87-
if (updateMappingRequest(index, type, mappingUpdate, timeout).get().isAcknowledged() == false) {
88-
throw new ElasticsearchTimeoutException("Failed to acknowledge mapping update within [" + timeout + "]");
89-
}
86+
updateMappingRequest(index, type, mappingUpdate, timeout).get();
9087
}
9188
}

server/src/test/java/org/elasticsearch/action/support/master/IndexingMasterFailoverIT.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ protected Settings nodeSettings(int nodeOrdinal) {
6666
* This retry logic is implemented in TransportMasterNodeAction and tested by the following master failover scenario.
6767
*/
6868
@TestLogging("_root:DEBUG")
69-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/30844")
7069
public void testMasterFailoverDuringIndexingWithMappingChanges() throws Throwable {
7170
logger.info("--> start 4 nodes, 3 master, 1 data");
7271

server/src/test/java/org/elasticsearch/cluster/routing/PrimaryAllocationIT.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
*/
2121

2222
import com.carrotsearch.hppc.cursors.IntObjectCursor;
23+
import org.elasticsearch.action.DocWriteResponse;
2324
import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteRequestBuilder;
2425
import org.elasticsearch.action.admin.indices.shards.IndicesShardStoresResponse;
26+
import org.elasticsearch.action.bulk.BulkResponse;
2527
import org.elasticsearch.action.index.IndexResponse;
2628
import org.elasticsearch.action.support.ActiveShardCount;
2729
import org.elasticsearch.cluster.ClusterState;
@@ -30,6 +32,7 @@
3032
import org.elasticsearch.cluster.routing.allocation.command.AllocateEmptyPrimaryAllocationCommand;
3133
import org.elasticsearch.cluster.routing.allocation.command.AllocateStalePrimaryAllocationCommand;
3234
import org.elasticsearch.cluster.service.ClusterService;
35+
import org.elasticsearch.common.Strings;
3336
import org.elasticsearch.common.collect.ImmutableOpenIntMap;
3437
import org.elasticsearch.common.settings.Settings;
3538
import org.elasticsearch.common.util.set.Sets;
@@ -89,6 +92,34 @@ protected Settings nodeSettings(int nodeOrdinal) {
8992
.put(TestZenDiscovery.USE_MOCK_PINGS.getKey(), false).build();
9093
}
9194

95+
public void testBulkWeirdScenario() throws Exception {
96+
String master = internalCluster().startMasterOnlyNode(Settings.EMPTY);
97+
internalCluster().startDataOnlyNodes(2);
98+
99+
assertAcked(client().admin().indices().prepareCreate("test").setSettings(Settings.builder()
100+
.put("index.number_of_shards", 1).put("index.number_of_replicas", 1)).get());
101+
ensureGreen();
102+
103+
BulkResponse bulkResponse = client().prepareBulk()
104+
.add(client().prepareIndex().setIndex("test").setType("_doc").setId("1").setSource("field1", "value1"))
105+
.add(client().prepareUpdate().setIndex("test").setType("_doc").setId("1").setDoc("field2", "value2"))
106+
.execute().actionGet();
107+
108+
assertThat(bulkResponse.hasFailures(), equalTo(false));
109+
assertThat(bulkResponse.getItems().length, equalTo(2));
110+
111+
logger.info(Strings.toString(bulkResponse, true, true));
112+
113+
internalCluster().assertSeqNos();
114+
115+
assertThat(bulkResponse.getItems()[0].getResponse().getId(), equalTo("1"));
116+
assertThat(bulkResponse.getItems()[0].getResponse().getVersion(), equalTo(1L));
117+
assertThat(bulkResponse.getItems()[0].getResponse().getResult(), equalTo(DocWriteResponse.Result.CREATED));
118+
assertThat(bulkResponse.getItems()[1].getResponse().getId(), equalTo("1"));
119+
assertThat(bulkResponse.getItems()[1].getResponse().getVersion(), equalTo(2L));
120+
assertThat(bulkResponse.getItems()[1].getResponse().getResult(), equalTo(DocWriteResponse.Result.UPDATED));
121+
}
122+
92123
private void createStaleReplicaScenario(String master) throws Exception {
93124
client().prepareIndex("test", "type1").setSource(jsonBuilder()
94125
.startObject().field("field", "value1").endObject()).get();

server/src/test/java/org/elasticsearch/indices/state/RareClusterStateIT.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.elasticsearch.ElasticsearchParseException;
2323
import org.elasticsearch.Version;
24+
import org.elasticsearch.action.ActionFuture;
2425
import org.elasticsearch.action.ActionListener;
2526
import org.elasticsearch.action.index.IndexResponse;
2627
import org.elasticsearch.action.support.master.AcknowledgedResponse;
@@ -57,6 +58,7 @@
5758

5859
import static java.util.Collections.emptyMap;
5960
import static java.util.Collections.emptySet;
61+
import static org.elasticsearch.action.DocWriteResponse.Result.CREATED;
6062
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
6163
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
6264
import static org.hamcrest.Matchers.equalTo;
@@ -392,6 +394,24 @@ public void onFailure(Exception e) {
392394
// Wait for document to be indexed on primary
393395
assertBusy(() -> assertTrue(client().prepareGet("index", "type", "1").setPreference("_primary").get().isExists()));
394396

397+
// index another document, this time using dynamic mappings.
398+
// The ack timeout of 0 on dynamic mapping updates makes it possible for the document to be indexed on the primary, even
399+
// if the dynamic mapping update is not applied on the replica yet.
400+
ActionFuture<IndexResponse> dynamicMappingsFut = client().prepareIndex("index", "type", "2").setSource("field2", 42).execute();
401+
402+
// ...and wait for second mapping to be available on master
403+
assertBusy(() -> {
404+
final IndicesService indicesService = internalCluster().getInstance(IndicesService.class, master);
405+
final IndexService indexService = indicesService.indexServiceSafe(index);
406+
assertNotNull(indexService);
407+
final MapperService mapperService = indexService.mapperService();
408+
DocumentMapper mapper = mapperService.documentMapper("type");
409+
assertNotNull(mapper);
410+
assertNotNull(mapper.mappers().getMapper("field2"));
411+
});
412+
413+
assertBusy(() -> assertTrue(client().prepareGet("index", "type", "2").get().isExists()));
414+
395415
// The mappings have not been propagated to the replica yet as a consequence the document count not be indexed
396416
// We wait on purpose to make sure that the document is not indexed because the shard operation is stalled
397417
// and not just because it takes time to replicate the indexing request to the replica
@@ -410,6 +430,8 @@ public void onFailure(Exception e) {
410430
assertEquals(Arrays.toString(docResp.getShardInfo().getFailures()),
411431
2, docResp.getShardInfo().getTotal()); // both shards should have succeeded
412432
});
433+
434+
assertThat(dynamicMappingsFut.get().getResult(), equalTo(CREATED));
413435
}
414436

415437
}

0 commit comments

Comments
 (0)