Skip to content

Commit 5e148a9

Browse files
authored
Avoid changing tsid creation strategy for an index (#135514)
This avoids that the tsid and routing is calculated differently on the same index. Doing so would have the following consequences: * De-duplication would not work, for example, when a client re-transmits a batch as the id (which is based on the tsid) will be different. * When replaying a translog operation, the re-computed tsid and id will differ from the id stored in the translog. This would lead to a failure of the index operation.
1 parent da795ee commit 5e148a9

File tree

3 files changed

+38
-19
lines changed

3 files changed

+38
-19
lines changed

modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/TSDBIndexingIT.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
package org.elasticsearch.datastreams;
1010

11+
import org.elasticsearch.action.ActionFuture;
1112
import org.elasticsearch.action.DocWriteRequest;
1213
import org.elasticsearch.action.admin.indices.diskusage.AnalyzeIndexDiskUsageRequest;
1314
import org.elasticsearch.action.admin.indices.diskusage.TransportAnalyzeIndexDiskUsageAction;
@@ -31,6 +32,7 @@
3132
import org.elasticsearch.action.index.IndexRequest;
3233
import org.elasticsearch.action.search.SearchRequest;
3334
import org.elasticsearch.action.support.WriteRequest;
35+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
3436
import org.elasticsearch.cluster.metadata.ComponentTemplate;
3537
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
3638
import org.elasticsearch.cluster.metadata.IndexMetadata;
@@ -709,17 +711,20 @@ public void testAddDimensionToMapping() throws Exception {
709711
]
710712
}
711713
""", XContentType.JSON);
712-
assertAcked(client().execute(TransportPutMappingAction.TYPE, putMappingRequest).actionGet());
714+
ActionFuture<AcknowledgedResponse> putMappingFuture = client().execute(TransportPutMappingAction.TYPE, putMappingRequest);
713715
if (INDEX_DIMENSIONS_TSID_OPTIMIZATION_FEATURE_FLAG) {
716+
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, putMappingFuture::actionGet);
714717
assertThat(
715-
getSetting(dataStreamName, IndexMetadata.INDEX_ROUTING_PATH),
716-
containsInAnyOrder("metricset", "labels.*", "k8s.pod.name")
718+
exception.getMessage(),
719+
containsString("Cannot add dynamic templates that define dimension fields on an existing index with index.dimensions")
717720
);
721+
assertThat(getSetting(dataStreamName, IndexMetadata.INDEX_DIMENSIONS), containsInAnyOrder("metricset", "k8s.pod.name"));
722+
assertThat(getSetting(dataStreamName, IndexMetadata.INDEX_ROUTING_PATH), empty());
718723
} else {
724+
assertAcked(putMappingFuture);
719725
assertThat(getSetting(dataStreamName, IndexMetadata.INDEX_ROUTING_PATH), containsInAnyOrder("metricset"));
726+
assertThat(getSetting(dataStreamName, IndexMetadata.INDEX_DIMENSIONS), empty());
720727
}
721-
assertThat(getSetting(dataStreamName, IndexMetadata.INDEX_DIMENSIONS), empty());
722-
723728
indexWithPodNames(dataStreamName, Instant.now(), Map.of(), "dog", "cat");
724729
}
725730

modules/data-streams/src/main/java/org/elasticsearch/datastreams/DataStreamIndexSettingsProvider.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,15 @@ public void provideAdditionalSettings(
154154
}
155155

156156
/**
157-
* This is called when mappings are updated, so that the {@link IndexMetadata#getTimeSeriesDimensions()}
158-
* and {@link IndexMetadata#INDEX_ROUTING_PATH} settings are updated to match the new mappings.
159-
* Updates {@link IndexMetadata#getTimeSeriesDimensions} if a new dimension field is added to the mappings,
160-
* or sets {@link IndexMetadata#INDEX_ROUTING_PATH} if a new dimension field is added that doesn't allow for matching all
161-
* dimension fields via a wildcard pattern.
157+
* This is called when mappings are updated, so that the {@link IndexMetadata#INDEX_DIMENSIONS}
158+
* setting is updated if a new dimension field is added to the mappings.
159+
*
160+
* @throws IllegalArgumentException If a dynamic template that defines dimension fields is added to an existing index with
161+
* {@link IndexMetadata#getTimeSeriesDimensions()}.
162+
* Changing fom {@link IndexMetadata#INDEX_DIMENSIONS} to {@link IndexMetadata#INDEX_ROUTING_PATH}
163+
* is not allowed because it would violate the invariant that the same input document always results
164+
* in the same _id and _tsid.
165+
* Otherwise, data duplication or translog replay issues could occur.
162166
*/
163167
@Override
164168
public void onUpdateMappings(IndexMetadata indexMetadata, DocumentMapper documentMapper, Settings.Builder additionalSettings) {
@@ -172,11 +176,13 @@ public void onUpdateMappings(IndexMetadata indexMetadata, DocumentMapper documen
172176
boolean hasChanges = indexDimensions.size() != newIndexDimensions.size()
173177
&& new HashSet<>(indexDimensions).equals(new HashSet<>(newIndexDimensions)) == false;
174178
if (matchesAllDimensions == false) {
175-
// If the new dimensions don't match all potential dimension fields, we need to unset index.dimensions
176-
// and set index.routing_path instead.
177-
// This can happen if a new dynamic template with time_series_dimension: true is added to an existing index.
178-
additionalSettings.putList(INDEX_DIMENSIONS.getKey(), List.of());
179-
additionalSettings.putList(INDEX_ROUTING_PATH.getKey(), newIndexDimensions);
179+
throw new IllegalArgumentException(
180+
"Cannot add dynamic templates that define dimension fields on an existing index with "
181+
+ INDEX_DIMENSIONS.getKey()
182+
+ ". "
183+
+ "Please change the index template and roll over the data stream "
184+
+ "instead of modifying the mappings of the backing indices."
185+
);
180186
} else if (hasChanges) {
181187
additionalSettings.putList(INDEX_DIMENSIONS.getKey(), newIndexDimensions);
182188
}

modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamIndexSettingsProviderTests.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -956,10 +956,18 @@ public void testAddDynamicTemplate() throws Exception {
956956
}
957957
""";
958958
// we don't support index.dimensions with dynamic templates so we'll unset index.dimensions
959-
Settings result = onUpdateMappings(null, "labels.*", mapping);
960-
assertThat(result.size(), equalTo(2));
961-
assertThat(IndexMetadata.INDEX_DIMENSIONS.get(result), empty());
962-
assertThat(IndexMetadata.INDEX_ROUTING_PATH.get(result), containsInAnyOrder("labels.*"));
959+
IllegalArgumentException exception = assertThrows(
960+
IllegalArgumentException.class,
961+
() -> onUpdateMappings(null, "labels.*", mapping)
962+
);
963+
assertThat(
964+
exception.getMessage(),
965+
equalTo(
966+
"Cannot add dynamic templates that define dimension fields on an existing index with index.dimensions. "
967+
+ "Please change the index template and roll over the data stream "
968+
+ "instead of modifying the mappings of the backing indices."
969+
)
970+
);
963971
}
964972

965973
private Settings generateTsdbSettings(String mapping, Instant now) throws IOException {

0 commit comments

Comments
 (0)