diff --git a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java index 114715bdab76e..74d248a4cb650 100644 --- a/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java +++ b/modules/data-streams/src/main/java/org/elasticsearch/datastreams/action/TransportCreateDataStreamAction.java @@ -75,8 +75,7 @@ protected void masterOperation( request.getStartTime(), systemDataStreamDescriptor, request.masterNodeTimeout(), - request.ackTimeout(), - true + request.ackTimeout() ); metadataCreateDataStreamService.createDataStream(updateRequest, listener); } diff --git a/modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamGetWriteIndexTests.java b/modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamGetWriteIndexTests.java index e6ac0bfe7561a..a0b53af1f0eeb 100644 --- a/modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamGetWriteIndexTests.java +++ b/modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamGetWriteIndexTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.cluster.metadata.MetadataIndexAliasesService; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; +import org.elasticsearch.cluster.metadata.RerouteBehavior; import org.elasticsearch.cluster.metadata.Template; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.WriteLoadForecaster; @@ -332,10 +333,9 @@ private ClusterState createDataStream(ClusterState state, String name, Instant t time.toEpochMilli(), null, TimeValue.ZERO, - TimeValue.ZERO, - false + TimeValue.ZERO ); - return createDataStreamService.createDataStream(request, state, ActionListener.noop(), false); + return createDataStreamService.createDataStream(request, state, RerouteBehavior.SKIP_REROUTE, ActionListener.noop(), false); } private MetadataRolloverService.RolloverResult rolloverOver(ClusterState state, String name, Instant time) throws Exception { diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/AutoCreateAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/AutoCreateAction.java index 095e2303d26c2..21e0ec90cd2dd 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/AutoCreateAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/AutoCreateAction.java @@ -33,6 +33,7 @@ import org.elasticsearch.cluster.metadata.MetadataIndexTemplateService; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; +import org.elasticsearch.cluster.metadata.RerouteBehavior; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.routing.allocation.AllocationService; @@ -289,14 +290,12 @@ ClusterState execute( request.index(), dataStreamDescriptor, request.masterNodeTimeout(), - request.ackTimeout(), - false + request.ackTimeout() ); - assert createRequest.performReroute() == false - : "rerouteCompletionIsNotRequired() assumes reroute is not called by underlying service"; ClusterState clusterState = metadataCreateDataStreamService.createDataStream( createRequest, currentState, + RerouteBehavior.SKIP_REROUTE, rerouteCompletionIsNotRequired(), request.isInitializeFailureStore() ); @@ -372,12 +371,11 @@ ClusterState execute( updateRequest = buildUpdateRequest(projectId, indexName); } - assert updateRequest.performReroute() == false - : "rerouteCompletionIsNotRequired() assumes reroute is not called by underlying service"; final var clusterState = createIndexService.applyCreateIndexRequest( currentState, updateRequest, false, + RerouteBehavior.SKIP_REROUTE, rerouteCompletionIsNotRequired() ); taskContext.success(getAckListener(indexName, allocationActionMultiListener)); @@ -392,7 +390,7 @@ private CreateIndexClusterStateUpdateRequest buildUpdateRequest(ProjectId projec projectId, indexName, request.index() - ).performReroute(false); + ); logger.debug("Auto-creating index {}", indexName); return updateRequest; } @@ -414,7 +412,7 @@ private CreateIndexClusterStateUpdateRequest buildSystemIndexUpdateRequest( projectId, concreteIndexName, request.index() - ).performReroute(false); + ); updateRequest.waitForActiveShards(ActiveShardCount.ALL); diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java index a9983af26d735..1f175031c8d40 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/create/CreateIndexClusterStateUpdateRequest.java @@ -49,8 +49,6 @@ public class CreateIndexClusterStateUpdateRequest { private ActiveShardCount waitForActiveShards = ActiveShardCount.DEFAULT; - private boolean performReroute = true; - private ComposableIndexTemplate matchingTemplate; private boolean settingsSystemProvided = false; @@ -202,15 +200,6 @@ public CreateIndexClusterStateUpdateRequest dataStreamName(String dataStreamName return this; } - public boolean performReroute() { - return performReroute; - } - - public CreateIndexClusterStateUpdateRequest performReroute(boolean performReroute) { - this.performReroute = performReroute; - return this; - } - /** * @return The composable index template that matches with the index that will be created by this request. */ diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java index b4eb1fe8ed1bb..c9309f321533a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java @@ -36,6 +36,7 @@ import org.elasticsearch.cluster.metadata.MetadataIndexTemplateService; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; +import org.elasticsearch.cluster.metadata.RerouteBehavior; import org.elasticsearch.cluster.routing.allocation.WriteLoadForecaster; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; @@ -265,12 +266,11 @@ private RolloverResult rolloverAlias( rolloverIndexName, createIndexRequest ); - assert createIndexClusterStateRequest.performReroute() == false - : "rerouteCompletionIsNotRequired() assumes reroute is not called by underlying service"; ClusterState newState = createIndexService.applyCreateIndexRequest( projectState.cluster(), createIndexClusterStateRequest, silent, + RerouteBehavior.SKIP_REROUTE, rerouteCompletionIsNotRequired() ); @@ -419,13 +419,11 @@ yield new DataStreamAutoShardingEvent( now ); createIndexClusterStateRequest.setMatchingTemplate(templateV2); - assert createIndexClusterStateRequest.performReroute() == false - : "rerouteCompletionIsNotRequired() assumes reroute is not called by underlying service"; - newState = createIndexService.applyCreateIndexRequest( projectState.cluster(), createIndexClusterStateRequest, silent, + RerouteBehavior.SKIP_REROUTE, (builder, indexMetadata) -> { downgradeBrokenTsdbBackingIndices(dataStream, builder); builder.put( @@ -581,8 +579,7 @@ static CreateIndexClusterStateUpdateRequest prepareCreateIndexRequest( return new CreateIndexClusterStateUpdateRequest(cause, projectId, targetIndexName, providedIndexName).settings(b.build()) .aliases(createIndexRequest.aliases()) .waitForActiveShards(ActiveShardCount.NONE) // not waiting for shards here, will wait on the alias switch operation - .mappings(createIndexRequest.mappings()) - .performReroute(false); + .mappings(createIndexRequest.mappings()); } /** diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamService.java index d0b32df29077a..1fe482e1cbeb7 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamService.java @@ -109,7 +109,13 @@ public void createDataStream(CreateDataStreamClusterStateUpdateRequest request, public ClusterState execute(ClusterState currentState) throws Exception { // When we're manually creating a data stream (i.e. not an auto creation), we don't need to initialize the failure store // because we don't need to redirect any failures in the same request. - ClusterState clusterState = createDataStream(request, currentState, delegate.reroute(), false); + ClusterState clusterState = createDataStream( + request, + currentState, + RerouteBehavior.PERFORM_REROUTE, + delegate.reroute(), + false + ); DataStream createdDataStream = clusterState.metadata().getProject(request.projectId()).dataStreams().get(request.name); firstBackingIndexRef.set(createdDataStream.getIndices().get(0).getName()); if (createdDataStream.getFailureIndices().isEmpty() == false) { @@ -129,6 +135,7 @@ private void submitUnbatchedTask(@SuppressWarnings("SameParameterValue") String public ClusterState createDataStream( CreateDataStreamClusterStateUpdateRequest request, ClusterState current, + RerouteBehavior rerouteBehavior, ActionListener rerouteListener, boolean initializeFailureStore ) throws Exception { @@ -138,6 +145,7 @@ public ClusterState createDataStream( current, isDslOnlyMode, request, + rerouteBehavior, rerouteListener, initializeFailureStore ); @@ -149,8 +157,7 @@ public record CreateDataStreamClusterStateUpdateRequest( long startTime, @Nullable SystemDataStreamDescriptor systemDataStreamDescriptor, TimeValue masterNodeTimeout, - TimeValue ackTimeout, - boolean performReroute + TimeValue ackTimeout ) { public CreateDataStreamClusterStateUpdateRequest { Objects.requireNonNull(name); @@ -159,7 +166,7 @@ public record CreateDataStreamClusterStateUpdateRequest( } public CreateDataStreamClusterStateUpdateRequest(final ProjectId projectId, String name) { - this(projectId, name, null, TimeValue.ZERO, TimeValue.ZERO, true); + this(projectId, name, null, TimeValue.ZERO, TimeValue.ZERO); } public CreateDataStreamClusterStateUpdateRequest( @@ -167,10 +174,9 @@ public CreateDataStreamClusterStateUpdateRequest( String name, SystemDataStreamDescriptor systemDataStreamDescriptor, TimeValue masterNodeTimeout, - TimeValue ackTimeout, - boolean performReroute + TimeValue ackTimeout ) { - this(projectId, name, System.currentTimeMillis(), systemDataStreamDescriptor, masterNodeTimeout, ackTimeout, performReroute); + this(projectId, name, System.currentTimeMillis(), systemDataStreamDescriptor, masterNodeTimeout, ackTimeout); } public boolean isSystem() { @@ -184,6 +190,7 @@ static ClusterState createDataStream( ClusterState currentState, boolean isDslOnlyMode, CreateDataStreamClusterStateUpdateRequest request, + RerouteBehavior rerouteBehavior, ActionListener rerouteListener, boolean initializeFailureStore ) throws Exception { @@ -195,6 +202,7 @@ static ClusterState createDataStream( request, List.of(), null, + rerouteBehavior, rerouteListener, initializeFailureStore ); @@ -220,6 +228,7 @@ static ClusterState createDataStream( CreateDataStreamClusterStateUpdateRequest request, List backingIndices, IndexMetadata writeIndex, + RerouteBehavior rerouteBehavior, ActionListener rerouteListener, boolean initializeFailureStore ) throws Exception { @@ -304,6 +313,7 @@ static ClusterState createDataStream( metadataCreateIndexService, currentState, request, + rerouteBehavior, rerouteListener, dataStreamName, systemDataStreamDescriptor, @@ -374,6 +384,7 @@ private static ClusterState createBackingIndex( MetadataCreateIndexService metadataCreateIndexService, ClusterState currentState, CreateDataStreamClusterStateUpdateRequest request, + RerouteBehavior rerouteBehavior, ActionListener rerouteListener, String dataStreamName, SystemDataStreamDescriptor systemDataStreamDescriptor, @@ -389,7 +400,6 @@ private static ClusterState createBackingIndex( ).dataStreamName(dataStreamName) .systemDataStreamDescriptor(systemDataStreamDescriptor) .nameResolvedInstant(request.startTime()) - .performReroute(request.performReroute()) .setMatchingTemplate(template); if (isSystem) { @@ -399,7 +409,13 @@ private static ClusterState createBackingIndex( } try { - currentState = metadataCreateIndexService.applyCreateIndexRequest(currentState, createIndexRequest, false, rerouteListener); + currentState = metadataCreateIndexService.applyCreateIndexRequest( + currentState, + createIndexRequest, + false, + rerouteBehavior, + rerouteListener + ); } catch (ResourceAlreadyExistsException e) { // Rethrow as ElasticsearchStatusException, so that bulk transport action doesn't ignore it during // auto index/data stream creation. @@ -436,7 +452,6 @@ public static ClusterState createFailureStoreIndex( failureStoreIndexName ).dataStreamName(dataStreamName) .nameResolvedInstant(nameResolvedInstant) - .performReroute(false) .setMatchingTemplate(template) .settings(indexSettings) .isFailureIndex(true) @@ -447,6 +462,7 @@ public static ClusterState createFailureStoreIndex( currentState, createIndexRequest, false, + RerouteBehavior.SKIP_REROUTE, metadataTransformer, AllocationActionListener.rerouteCompletionIsNotRequired() ); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java index 34f053d5e6408..2023c51e76607 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java @@ -257,11 +257,9 @@ public void validateIndexLimit(ProjectMetadata projectMetadata, CreateIndexClust if (maxIndicesPerProjectEnabled == false) { return; } - if (systemIndices.isSystemIndex(request.index()) || systemIndices.isSystemIndexBackingDataStream(request.index())) { return; } - if (systemIndices.isFeatureAssociatedIndex(request.index())) { return; } @@ -448,7 +446,7 @@ private void onlyCreateIndex( @Override public ClusterState execute(ClusterState currentState) throws Exception { - return applyCreateIndexRequest(currentState, request, false, null, delegate.reroute()); + return applyCreateIndexRequest(currentState, request, false, RerouteBehavior.PERFORM_REROUTE, delegate.reroute()); } @Override @@ -486,6 +484,7 @@ public ClusterState applyCreateIndexRequest( ClusterState currentState, CreateIndexClusterStateUpdateRequest request, boolean silent, + RerouteBehavior rerouteBehavior, BiConsumer metadataTransformer, ActionListener rerouteListener ) throws Exception { @@ -516,6 +515,7 @@ public ClusterState applyCreateIndexRequest( silent, sourceMetadata, metadataTransformer, + rerouteBehavior, rerouteListener ); } else { @@ -524,14 +524,28 @@ public ClusterState applyCreateIndexRequest( // The index being created is for a system data stream, so the backing index will also be a system index if (request.systemDataStreamDescriptor() != null) { - return applyCreateIndexRequestForSystemDataStream(currentState, request, silent, metadataTransformer, rerouteListener); + return applyCreateIndexRequestForSystemDataStream( + currentState, + request, + silent, + metadataTransformer, + rerouteBehavior, + rerouteListener + ); } SystemIndexDescriptor descriptor = systemIndices.findMatchingDescriptor(request.index()); // ignore all templates for all system indices that do not allow templates. // Essentially, all but .kibana indices, see KibanaPlugin.java. if (Objects.nonNull(descriptor) && descriptor.allowsTemplates() == false) { - return applyCreateIndexRequestForSystemIndex(currentState, request, silent, descriptor.getIndexPattern(), rerouteListener); + return applyCreateIndexRequestForSystemIndex( + currentState, + request, + silent, + descriptor.getIndexPattern(), + rerouteBehavior, + rerouteListener + ); } // Hidden indices apply templates slightly differently (ignoring wildcard '*' @@ -549,6 +563,7 @@ public ClusterState applyCreateIndexRequest( silent, templateFromRequest, metadataTransformer, + rerouteBehavior, rerouteListener ); } @@ -569,6 +584,7 @@ public ClusterState applyCreateIndexRequest( silent, v2Template, metadataTransformer, + rerouteBehavior, rerouteListener ); } else { @@ -596,6 +612,7 @@ public ClusterState applyCreateIndexRequest( silent, v1Templates, metadataTransformer, + rerouteBehavior, rerouteListener ); } @@ -606,9 +623,10 @@ public ClusterState applyCreateIndexRequest( ClusterState currentState, CreateIndexClusterStateUpdateRequest request, boolean silent, + RerouteBehavior rerouteBehavior, ActionListener rerouteListener ) throws Exception { - return applyCreateIndexRequest(currentState, request, silent, null, rerouteListener); + return applyCreateIndexRequest(currentState, request, silent, rerouteBehavior, null, rerouteListener); } /** @@ -625,6 +643,8 @@ public ClusterState applyCreateIndexRequest( * @param templatesApplied a list of the names of the templates applied, for logging * @param metadataTransformer if provided, a function that may alter cluster metadata in the same cluster state update that * creates the index + * @param rerouteBehavior controls whether allocation reroute() is triggered after index creation + * @param rerouteListener listener called when reroute completes, or immediately if rerouting is skipped * @return a new cluster state with the index added */ private ClusterState applyCreateIndexWithTemporaryService( @@ -637,6 +657,7 @@ private ClusterState applyCreateIndexWithTemporaryService( final Function> aliasSupplier, final List templatesApplied, final BiConsumer metadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { // create the index here (on the master) to validate it can be created, as well as adding the mapping @@ -696,7 +717,12 @@ private ClusterState applyCreateIndexWithTemporaryService( allocationService.getShardRoutingRoleStrategy() ); assert assertHasRefreshBlock(indexMetadata, updated.projectState(request.projectId())); - if (request.performReroute()) { + + if (rerouteBehavior == RerouteBehavior.SKIP_REROUTE) { + if (rerouteListener != null) { + rerouteListener.onResponse(null); + } + } else { updated = allocationService.reroute( updated, "index [" + indexMetadata.getIndex().getName() + "] created in project [" + request.projectId() + "]", @@ -744,6 +770,7 @@ private ClusterState applyCreateIndexRequestWithV1Templates( final boolean silent, final List templates, final BiConsumer projectMetadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { logger.debug( @@ -807,6 +834,7 @@ private ClusterState applyCreateIndexRequestWithV1Templates( ), templates.stream().map(IndexTemplateMetadata::getName).collect(toList()), projectMetadataTransformer, + rerouteBehavior, rerouteListener ); } @@ -817,6 +845,7 @@ private ClusterState applyCreateIndexRequestWithV2Template( final boolean silent, final String templateName, final BiConsumer projectMetadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { logger.debug("applying create index request using composable template [{}]", templateName); @@ -836,7 +865,15 @@ private ClusterState applyCreateIndexRequestWithV2Template( + "use create data stream api instead" ); } - return applyCreateIndexRequestWithV2Template(currentState, request, silent, template, projectMetadataTransformer, rerouteListener); + return applyCreateIndexRequestWithV2Template( + currentState, + request, + silent, + template, + projectMetadataTransformer, + rerouteBehavior, + rerouteListener + ); } private ClusterState applyCreateIndexRequestWithV2Template( @@ -845,6 +882,7 @@ private ClusterState applyCreateIndexRequestWithV2Template( final boolean silent, final ComposableIndexTemplate template, final BiConsumer projectMetadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { @@ -900,6 +938,7 @@ private ClusterState applyCreateIndexRequestWithV2Template( ), Collections.singletonList("provided in request"), projectMetadataTransformer, + rerouteBehavior, rerouteListener ); } @@ -909,6 +948,7 @@ private ClusterState applyCreateIndexRequestForSystemIndex( final CreateIndexClusterStateUpdateRequest request, final boolean silent, final String indexPattern, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { logger.debug("applying create index request for system index [{}] matching pattern [{}]", request.index(), indexPattern); @@ -955,6 +995,7 @@ private ClusterState applyCreateIndexRequestForSystemIndex( ), List.of(), null, + rerouteBehavior, rerouteListener ); } @@ -964,6 +1005,7 @@ private ClusterState applyCreateIndexRequestForSystemDataStream( final CreateIndexClusterStateUpdateRequest request, final boolean silent, final BiConsumer projectMetadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { Objects.requireNonNull(request.systemDataStreamDescriptor()); @@ -1022,6 +1064,7 @@ private ClusterState applyCreateIndexRequestForSystemDataStream( ), List.of(), projectMetadataTransformer, + rerouteBehavior, rerouteListener ); } @@ -1077,6 +1120,7 @@ private ClusterState applyCreateIndexRequestWithExistingMetadata( final boolean silent, final IndexMetadata sourceMetadata, final BiConsumer projectMetadataTransformer, + final RerouteBehavior rerouteBehavior, final ActionListener rerouteListener ) throws Exception { logger.info("applying create index request using existing index [{}] metadata", sourceMetadata.getIndex().getName()); @@ -1131,6 +1175,7 @@ private ClusterState applyCreateIndexRequestWithExistingMetadata( ), List.of(), projectMetadataTransformer, + rerouteBehavior, rerouteListener ); } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataMigrateToDataStreamService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataMigrateToDataStreamService.java index 607ab79ffe59f..1e800c0f81f66 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataMigrateToDataStreamService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataMigrateToDataStreamService.java @@ -177,6 +177,7 @@ static ClusterState migrateToDataStream( req, backingIndices, updatedState.metadata().getProject(project.id()).index(writeIndex), + RerouteBehavior.PERFORM_REROUTE, listener, // No need to initialize the failure store when migrating to a data stream. false diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/RerouteBehavior.java b/server/src/main/java/org/elasticsearch/cluster/metadata/RerouteBehavior.java new file mode 100644 index 0000000000000..d3cee53951629 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/RerouteBehavior.java @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.cluster.metadata; + +/** + * Specifies whether reroute() should be called after applying request. + */ +public enum RerouteBehavior { + /** Invoke reroute after applying the request. */ + PERFORM_REROUTE, + /** Do not reroute; the caller is responsible for ensuring that a follow-up reroute occurs. */ + SKIP_REROUTE; + + /** + * Returns {@link #PERFORM_REROUTE} if either {@code this} or {@code other} is {@link #PERFORM_REROUTE}. + */ + public RerouteBehavior or(RerouteBehavior other) { + if (this == PERFORM_REROUTE || other == PERFORM_REROUTE) { + return PERFORM_REROUTE; + } + return SKIP_REROUTE; + } +} diff --git a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/AllocationActionListener.java b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/AllocationActionListener.java index 2d7e35613b698..9a59b9374bfea 100644 --- a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/AllocationActionListener.java +++ b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/allocator/AllocationActionListener.java @@ -28,10 +28,10 @@ public class AllocationActionListener { private final SetOnce>> additionalResponseHeaders = new SetOnce<>(); /** - * This listener could be used when reroute completion (such as even balancing shards across the cluster) is not required for the - * completion of the caller operation. + * Returns a no-op listener for callers that do not need to wait for reroute to finish (e.g. shard rebalancing across the cluster) + * before completing their own operation. * - * For example, it is required to compute the desired balance to properly allocate newly created index, but it is not when deleting one. + * For example, waiting for reroute is needed to allocate shards for a newly created index, but not when deleting one. */ public static ActionListener rerouteCompletionIsNotRequired() { return ActionListener.noop(); diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java index 2177733ad3f86..05a77af871a5d 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java @@ -37,6 +37,7 @@ import org.elasticsearch.cluster.metadata.MetadataIndexAliasesService; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; +import org.elasticsearch.cluster.metadata.RerouteBehavior; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.project.TestProjectResolvers; import org.elasticsearch.cluster.routing.RecoverySource; @@ -382,7 +383,11 @@ public void testConditionEvaluationWhenAliasToWriteAndReadIndicesConsidersOnlyPr .putProjectMetadata(ProjectMetadata.builder(projectId).put(indexMetadata).put(indexMetadata2)) .build(); - when(mockCreateIndexService.applyCreateIndexRequest(any(), any(), anyBoolean(), any())).thenReturn(stateBefore); + when(mockCreateIndexService.applyCreateIndexRequest(any(), any(), anyBoolean(), any(RerouteBehavior.class), any())).thenReturn( + stateBefore + ); + when(mockCreateIndexService.applyCreateIndexRequest(any(), any(), anyBoolean(), any(RerouteBehavior.class), any(), any())) + .thenReturn(stateBefore); when(mdIndexAliasesService.applyAliasActions(any(), any())).thenReturn(stateBefore); final TransportRolloverAction transportRolloverAction = new TransportRolloverAction( diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamServiceTests.java index ec18627fca5b9..1b67dd4051ed5 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateDataStreamServiceTests.java @@ -70,6 +70,7 @@ public void testCreateDataStream() throws Exception { cs, true, req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -106,6 +107,7 @@ public void testCreateDataStreamLogsdb() throws Exception { cs, true, req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -148,6 +150,7 @@ public void testCreateDataStreamWithAliasFromTemplate() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -226,6 +229,7 @@ public void testCreateDataStreamWithAliasFromComponentTemplate() throws Exceptio cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -282,6 +286,7 @@ public void testCreateDataStreamWithFailureStoreInitialized() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), true ); @@ -326,6 +331,7 @@ public void testCreateDataStreamWithFailureStoreUninitialized() throws Exception cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -367,6 +373,7 @@ public void testCreateDataStreamWithFailureStoreWithRefreshRate() throws Excepti cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), true ); @@ -395,8 +402,7 @@ public void testCreateSystemDataStream() throws Exception { dataStreamName, systemDataStreamDescriptor(), TimeValue.MAX_VALUE, - TimeValue.ZERO, - true + TimeValue.ZERO ); ClusterState newState = MetadataCreateDataStreamService.createDataStream( metadataCreateIndexService, @@ -404,6 +410,7 @@ public void testCreateSystemDataStream() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ); @@ -440,6 +447,7 @@ public void testCreateDuplicateDataStream() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -463,6 +471,7 @@ public void testCreateDataStreamWithInvalidName() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -486,6 +495,7 @@ public void testCreateDataStreamWithUppercaseCharacters() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -509,6 +519,7 @@ public void testCreateDataStreamStartingWithPeriod() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -532,6 +543,7 @@ public void testCreateDataStreamNoTemplate() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -556,6 +568,7 @@ public void testCreateDataStreamNoValidTemplate() throws Exception { cs, randomBoolean(), req, + RerouteBehavior.PERFORM_REROUTE, ActionListener.noop(), false ) @@ -591,10 +604,24 @@ private static MetadataCreateIndexService getMetadataCreateIndexService() throws ); return ClusterState.builder(currentState).putProjectMetadata(b.build()).build(); }; - when(s.applyCreateIndexRequest(any(ClusterState.class), any(CreateIndexClusterStateUpdateRequest.class), anyBoolean(), any())) - .thenAnswer(objectAnswer); when( - s.applyCreateIndexRequest(any(ClusterState.class), any(CreateIndexClusterStateUpdateRequest.class), anyBoolean(), any(), any()) + s.applyCreateIndexRequest( + any(ClusterState.class), + any(CreateIndexClusterStateUpdateRequest.class), + anyBoolean(), + any(RerouteBehavior.class), + any() + ) + ).thenAnswer(objectAnswer); + when( + s.applyCreateIndexRequest( + any(ClusterState.class), + any(CreateIndexClusterStateUpdateRequest.class), + anyBoolean(), + any(RerouteBehavior.class), + any(), + any() + ) ).thenAnswer(objectAnswer); return s; diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java index 42384f977a93c..63c6de472a973 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java @@ -1862,7 +1862,13 @@ public void testSetPrivateSettingsFails() throws Exception { IndexCreationException exception = assertThrows( IndexCreationException.class, - () -> service.applyCreateIndexRequest(clusterService.state(), request, false, ActionListener.wrap(r -> {}, e -> {})) + () -> service.applyCreateIndexRequest( + clusterService.state(), + request, + false, + RerouteBehavior.PERFORM_REROUTE, + ActionListener.noop() + ) ); assertThat( exception.getCause().getMessage(), @@ -1895,7 +1901,13 @@ public void testSetPrivateSettingsSucceedsWhenSystemProvided() throws Exception ); try { - service.applyCreateIndexRequest(clusterService.state(), request, false, ActionListener.wrap(r -> {}, e -> {})); + service.applyCreateIndexRequest( + clusterService.state(), + request, + false, + RerouteBehavior.PERFORM_REROUTE, + ActionListener.noop() + ); } catch (Exception e) { fail(e, "did not expect private setting to be rejected when system provided"); } @@ -1928,7 +1940,13 @@ public void testIndexSettingProviderPrivateSetting() throws Exception { ); try { - service.applyCreateIndexRequest(clusterService.state(), request, false, ActionListener.wrap(r -> {}, e -> {})); + service.applyCreateIndexRequest( + clusterService.state(), + request, + false, + RerouteBehavior.PERFORM_REROUTE, + ActionListener.noop() + ); } catch (Exception e) { fail(e, "did not expect private setting to be rejected when added via IndexSettingProvider"); } diff --git a/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java b/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java index 7539f1d53a8ff..31be19a27ca80 100644 --- a/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java +++ b/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java @@ -37,6 +37,7 @@ import org.elasticsearch.cluster.metadata.MetadataCreateIndexService; import org.elasticsearch.cluster.metadata.ProjectId; import org.elasticsearch.cluster.metadata.ProjectMetadata; +import org.elasticsearch.cluster.metadata.RerouteBehavior; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.routing.allocation.DataTier; @@ -1016,6 +1017,7 @@ public ClusterState execute(ClusterState currentState) throws Exception { createIndexClusterStateUpdateRequest, true, // Copy index metadata from source index to downsample index + RerouteBehavior.PERFORM_REROUTE, (builder, indexMetadata) -> builder.put(copyIndexMetadata(sourceIndexMetadata, indexMetadata, indexScopedSettings)), delegate.reroute() );