Skip to content

Commit 1b31e05

Browse files
committed
Add hook to provide settings on mapping update
1 parent 7f5d17c commit 1b31e05

File tree

5 files changed

+99
-6
lines changed

5 files changed

+99
-6
lines changed

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataMappingService.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
import org.elasticsearch.common.Priority;
2525
import org.elasticsearch.common.Strings;
2626
import org.elasticsearch.common.compress.CompressedXContent;
27+
import org.elasticsearch.common.settings.Settings;
2728
import org.elasticsearch.core.IOUtils;
2829
import org.elasticsearch.core.TimeValue;
2930
import org.elasticsearch.index.Index;
31+
import org.elasticsearch.index.IndexSettingProvider;
32+
import org.elasticsearch.index.IndexSettingProviders;
3033
import org.elasticsearch.index.IndexVersion;
3134
import org.elasticsearch.index.mapper.DocumentMapper;
3235
import org.elasticsearch.index.mapper.MapperService;
@@ -53,10 +56,14 @@ public class MetadataMappingService {
5356
private final MasterServiceTaskQueue<PutMappingClusterStateUpdateTask> taskQueue;
5457

5558
@Inject
56-
public MetadataMappingService(ClusterService clusterService, IndicesService indicesService) {
59+
public MetadataMappingService(
60+
ClusterService clusterService,
61+
IndicesService indicesService,
62+
IndexSettingProviders indexSettingProviders
63+
) {
5764
this.clusterService = clusterService;
5865
this.indicesService = indicesService;
59-
this.taskQueue = clusterService.createTaskQueue("put-mapping", Priority.HIGH, new PutMappingExecutor());
66+
this.taskQueue = clusterService.createTaskQueue("put-mapping", Priority.HIGH, new PutMappingExecutor(indexSettingProviders));
6067
}
6168

6269
record PutMappingClusterStateUpdateTask(PutMappingClusterStateUpdateRequest request, ActionListener<AcknowledgedResponse> listener)
@@ -96,6 +103,16 @@ public TimeValue ackTimeout() {
96103
}
97104

98105
class PutMappingExecutor implements ClusterStateTaskExecutor<PutMappingClusterStateUpdateTask> {
106+
private final IndexSettingProviders indexSettingProviders;
107+
108+
PutMappingExecutor() {
109+
this(IndexSettingProviders.EMPTY);
110+
}
111+
112+
PutMappingExecutor(IndexSettingProviders indexSettingProviders) {
113+
this.indexSettingProviders = indexSettingProviders;
114+
}
115+
99116
@Override
100117
public ClusterState execute(BatchExecutionContext<PutMappingClusterStateUpdateTask> batchExecutionContext) throws Exception {
101118
Map<Index, MapperService> indexMapperServices = new HashMap<>();
@@ -126,7 +143,7 @@ public ClusterState execute(BatchExecutionContext<PutMappingClusterStateUpdateTa
126143
}
127144
}
128145

129-
private static ClusterState applyRequest(
146+
private ClusterState applyRequest(
130147
ClusterState currentState,
131148
PutMappingClusterStateUpdateRequest request,
132149
Map<Index, MapperService> indexMapperServices
@@ -200,9 +217,26 @@ private static ClusterState applyRequest(
200217
indexMetadataBuilder.putMapping(new MappingMetadata(docMapper));
201218
indexMetadataBuilder.putInferenceFields(docMapper.mappers().inferenceFields());
202219
}
220+
boolean updatedSettings = false;
221+
final Settings.Builder additionalIndexSettings = Settings.builder();
203222
if (updatedMapping) {
204223
indexMetadataBuilder.mappingVersion(1 + indexMetadataBuilder.mappingVersion())
205224
.mappingsUpdatedVersion(IndexVersion.current());
225+
for (IndexSettingProvider provider : indexSettingProviders.getIndexSettingProviders()) {
226+
Settings newAdditionalSettings = provider.onUpdateMappings(indexMetadata, docMapper);
227+
if (newAdditionalSettings.isEmpty() == false) {
228+
MetadataCreateIndexService.validateAdditionalSettings(provider, newAdditionalSettings, additionalIndexSettings);
229+
additionalIndexSettings.put(newAdditionalSettings);
230+
updatedSettings = true;
231+
}
232+
}
233+
}
234+
if (updatedSettings) {
235+
final Settings.Builder indexSettingsBuilder = Settings.builder();
236+
indexSettingsBuilder.put(indexMetadata.getSettings());
237+
indexSettingsBuilder.put(additionalIndexSettings.build());
238+
indexMetadataBuilder.settings(indexSettingsBuilder.build());
239+
indexMetadataBuilder.settingsVersion(1 + indexMetadata.getSettingsVersion());
206240
}
207241
/*
208242
* This implicitly increments the index metadata version and builds the index metadata. This means that we need to have

server/src/main/java/org/elasticsearch/index/IndexSettingProvider.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.elasticsearch.common.settings.Settings;
1717
import org.elasticsearch.core.CheckedFunction;
1818
import org.elasticsearch.core.Nullable;
19+
import org.elasticsearch.index.mapper.DocumentMapper;
1920
import org.elasticsearch.index.mapper.MapperService;
2021

2122
import java.io.IOException;
@@ -42,15 +43,29 @@ public interface IndexSettingProvider {
4243
* defined on the create index request
4344
* @param combinedTemplateMappings All the mappings resolved from the template that matches
4445
*/
45-
Settings getAdditionalIndexSettings(
46+
default Settings getAdditionalIndexSettings(
4647
String indexName,
4748
@Nullable String dataStreamName,
4849
@Nullable IndexMode templateIndexMode,
4950
ProjectMetadata projectMetadata,
5051
Instant resolvedAt,
5152
Settings indexTemplateAndCreateRequestSettings,
5253
List<CompressedXContent> combinedTemplateMappings
53-
);
54+
) {
55+
return Settings.EMPTY;
56+
}
57+
58+
/**
59+
* Called when the mappings for an index are updated.
60+
* This method can be used to update index settings based on the new mappings.
61+
*
62+
* @param indexMetadata the index metadata for the index being updated
63+
* @param documentMapper the document mapper containing the updated mappings
64+
* @return additional settings to be applied to the index or {@link Settings#EMPTY} if no additional settings are needed
65+
*/
66+
default Settings onUpdateMappings(IndexMetadata indexMetadata, DocumentMapper documentMapper) {
67+
return Settings.EMPTY;
68+
}
5469

5570
/**
5671
* Infrastructure class that holds services that can be used by {@link IndexSettingProvider} instances.

server/src/main/java/org/elasticsearch/index/IndexSettingProviders.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
public final class IndexSettingProviders {
2020

21+
public static IndexSettingProviders EMPTY = new IndexSettingProviders(Collections.emptySet());
22+
2123
private final Set<IndexSettingProvider> indexSettingProviders;
2224

2325
public IndexSettingProviders(Set<IndexSettingProvider> indexSettingProviders) {

server/src/test/java/org/elasticsearch/cluster/metadata/MetadataMappingServiceTests.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@
1414
import org.elasticsearch.cluster.service.ClusterService;
1515
import org.elasticsearch.cluster.service.ClusterStateTaskExecutorUtils;
1616
import org.elasticsearch.common.compress.CompressedXContent;
17+
import org.elasticsearch.common.settings.Settings;
1718
import org.elasticsearch.index.IndexService;
19+
import org.elasticsearch.index.IndexSettingProvider;
20+
import org.elasticsearch.index.IndexSettingProviders;
1821
import org.elasticsearch.index.IndexVersion;
22+
import org.elasticsearch.index.mapper.DocumentMapper;
1923
import org.elasticsearch.plugins.Plugin;
2024
import org.elasticsearch.test.ESSingleNodeTestCase;
2125
import org.elasticsearch.test.InternalSettingsPlugin;
2226

2327
import java.util.Collection;
2428
import java.util.Collections;
2529
import java.util.List;
30+
import java.util.Set;
2631

2732
import static org.hamcrest.Matchers.equalTo;
2833
import static org.hamcrest.Matchers.not;
@@ -135,6 +140,39 @@ public void testMappingVersionUnchanged() throws Exception {
135140
assertThat(resultingState.metadata().getProject().index("test").getMappingVersion(), equalTo(previousVersion));
136141
}
137142

143+
public void testUpdateSettings() throws Exception {
144+
final IndexService indexService = createIndex("test", client().admin().indices().prepareCreate("test"));
145+
final long previousVersion = indexService.getMetadata().getSettingsVersion();
146+
final MetadataMappingService mappingService = getInstanceFromNode(MetadataMappingService.class);
147+
final MetadataMappingService.PutMappingExecutor putMappingExecutor = mappingService.new PutMappingExecutor(
148+
new IndexSettingProviders(Set.of(new IndexSettingProvider() {
149+
@Override
150+
public Settings onUpdateMappings(IndexMetadata indexMetadata, DocumentMapper documentMapper) {
151+
return Settings.builder().put("index.mapping.total_fields.limit", 42).build();
152+
}
153+
}))
154+
);
155+
final ClusterService clusterService = getInstanceFromNode(ClusterService.class);
156+
final PutMappingClusterStateUpdateRequest request = new PutMappingClusterStateUpdateRequest(
157+
TEST_REQUEST_TIMEOUT,
158+
TEST_REQUEST_TIMEOUT,
159+
"""
160+
{ "properties": { "field": { "type": "text" }}}""",
161+
false,
162+
indexService.index()
163+
);
164+
final var resultingState = ClusterStateTaskExecutorUtils.executeAndAssertSuccessful(
165+
clusterService.state(),
166+
putMappingExecutor,
167+
singleTask(request)
168+
);
169+
assertThat(resultingState.metadata().getDefaultProject().index("test").getSettingsVersion(), equalTo(1 + previousVersion));
170+
assertThat(
171+
resultingState.metadata().getDefaultProject().index("test").getSettings().get("index.mapping.total_fields.limit"),
172+
equalTo("42")
173+
);
174+
}
175+
138176
private static List<MetadataMappingService.PutMappingClusterStateUpdateTask> singleTask(PutMappingClusterStateUpdateRequest request) {
139177
return Collections.singletonList(new MetadataMappingService.PutMappingClusterStateUpdateTask(request, ActionListener.running(() -> {
140178
throw new AssertionError("task should not complete publication");

server/src/test/java/org/elasticsearch/snapshots/SnapshotResiliencyTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2544,7 +2544,11 @@ public RecyclerBytesStreamOutput newNetworkBytesStream() {
25442544
VerifyNodeRepositoryCoordinationAction.TYPE,
25452545
new VerifyNodeRepositoryCoordinationAction.LocalAction(actionFilters, transportService, clusterService, client)
25462546
);
2547-
final MetadataMappingService metadataMappingService = new MetadataMappingService(clusterService, indicesService);
2547+
final MetadataMappingService metadataMappingService = new MetadataMappingService(
2548+
clusterService,
2549+
indicesService,
2550+
IndexSettingProviders.EMPTY
2551+
);
25482552

25492553
peerRecoverySourceService = new PeerRecoverySourceService(
25502554
transportService,

0 commit comments

Comments
 (0)