Skip to content

Commit a3cdbda

Browse files
authored
Make the TransportRolloverAction execute in one cluster state update (#50388) (#50442)
This commit makes the TransportRolloverAction more resilient, by having it execute only one cluster state update that creates the new (rollover index), rolls over the alias from the source to the target index and set the RolloverInfo on the source index. Before these 3 steps were represented as 3 chained cluster state updates, which would've seen the user manually intervene if, say, the alias rollover cluster state update (second in the chain) failed but the creation of the rollover index (first in the chain) update succeeded * Rename innerExecute to applyAliasActions (cherry picked from commit 1ba4339) Signed-off-by: Andrei Dan <[email protected]>
1 parent 975cc99 commit a3cdbda

File tree

5 files changed

+82
-102
lines changed

5 files changed

+82
-102
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java

Lines changed: 49 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.elasticsearch.action.admin.indices.rollover;
2121

2222
import org.elasticsearch.action.ActionListener;
23-
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesClusterStateUpdateRequest;
2423
import org.elasticsearch.action.admin.indices.create.CreateIndexClusterStateUpdateRequest;
2524
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
2625
import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction;
@@ -150,56 +149,44 @@ public void onResponse(IndicesStatsResponse statsResponse) {
150149
new RolloverResponse(sourceIndexName, rolloverIndexName, conditionResults, true, false, false, false));
151150
return;
152151
}
153-
List<Condition<?>> metConditions = rolloverRequest.getConditions().values().stream()
152+
List<Condition<?>> metConditions = rolloverRequest.getConditions().values().stream()
154153
.filter(condition -> conditionResults.get(condition.toString())).collect(Collectors.toList());
155154
if (conditionResults.size() == 0 || metConditions.size() > 0) {
156-
CreateIndexClusterStateUpdateRequest updateRequest = prepareCreateIndexRequest(unresolvedName, rolloverIndexName,
157-
rolloverRequest);
158-
createIndexService.createIndex(updateRequest, ActionListener.wrap(createIndexClusterStateUpdateResponse -> {
159-
final IndicesAliasesClusterStateUpdateRequest aliasesUpdateRequest;
160-
if (explicitWriteIndex) {
161-
aliasesUpdateRequest = prepareRolloverAliasesWriteIndexUpdateRequest(sourceIndexName,
162-
rolloverIndexName, rolloverRequest);
163-
} else {
164-
aliasesUpdateRequest = prepareRolloverAliasesUpdateRequest(sourceIndexName,
165-
rolloverIndexName, rolloverRequest);
155+
CreateIndexClusterStateUpdateRequest createIndexRequest = prepareCreateIndexRequest(unresolvedName,
156+
rolloverIndexName, rolloverRequest);
157+
clusterService.submitStateUpdateTask("rollover_index source [" + sourceIndexName + "] to target ["
158+
+ rolloverIndexName + "]", new ClusterStateUpdateTask() {
159+
@Override
160+
public ClusterState execute(ClusterState currentState) throws Exception {
161+
ClusterState newState = createIndexService.applyCreateIndexRequest(currentState, createIndexRequest);
162+
newState = indexAliasesService.applyAliasActions(newState,
163+
rolloverAliasToNewIndex(sourceIndexName, rolloverIndexName, rolloverRequest, explicitWriteIndex));
164+
RolloverInfo rolloverInfo = new RolloverInfo(rolloverRequest.getAlias(), metConditions,
165+
threadPool.absoluteTimeInMillis());
166+
return ClusterState.builder(newState)
167+
.metaData(MetaData.builder(newState.metaData())
168+
.put(IndexMetaData.builder(newState.metaData().index(sourceIndexName))
169+
.putRolloverInfo(rolloverInfo))).build();
166170
}
167-
indexAliasesService.indicesAliases(aliasesUpdateRequest,
168-
ActionListener.wrap(aliasClusterStateUpdateResponse -> {
169-
if (aliasClusterStateUpdateResponse.isAcknowledged()) {
170-
clusterService.submitStateUpdateTask("update_rollover_info", new ClusterStateUpdateTask() {
171-
@Override
172-
public ClusterState execute(ClusterState currentState) {
173-
RolloverInfo rolloverInfo = new RolloverInfo(rolloverRequest.getAlias(), metConditions,
174-
threadPool.absoluteTimeInMillis());
175-
return ClusterState.builder(currentState)
176-
.metaData(MetaData.builder(currentState.metaData())
177-
.put(IndexMetaData.builder(currentState.metaData().index(sourceIndexName))
178-
.putRolloverInfo(rolloverInfo))).build();
179-
}
180171

181-
@Override
182-
public void onFailure(String source, Exception e) {
183-
listener.onFailure(e);
184-
}
172+
@Override
173+
public void onFailure(String source, Exception e) {
174+
listener.onFailure(e);
175+
}
185176

186-
@Override
187-
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
188-
activeShardsObserver.waitForActiveShards(new String[]{rolloverIndexName},
189-
rolloverRequest.getCreateIndexRequest().waitForActiveShards(),
190-
rolloverRequest.masterNodeTimeout(),
191-
isShardsAcknowledged -> listener.onResponse(new RolloverResponse(
192-
sourceIndexName, rolloverIndexName, conditionResults, false, true, true,
193-
isShardsAcknowledged)),
194-
listener::onFailure);
195-
}
196-
});
197-
} else {
198-
listener.onResponse(new RolloverResponse(sourceIndexName, rolloverIndexName, conditionResults,
199-
false, true, false, false));
200-
}
201-
}, listener::onFailure));
202-
}, listener::onFailure));
177+
@Override
178+
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
179+
if (newState.equals(oldState) == false) {
180+
activeShardsObserver.waitForActiveShards(new String[]{rolloverIndexName},
181+
rolloverRequest.getCreateIndexRequest().waitForActiveShards(),
182+
rolloverRequest.masterNodeTimeout(),
183+
isShardsAcknowledged -> listener.onResponse(new RolloverResponse(
184+
sourceIndexName, rolloverIndexName, conditionResults, false, true, true,
185+
isShardsAcknowledged)),
186+
listener::onFailure);
187+
}
188+
}
189+
});
203190
} else {
204191
// conditions not met
205192
listener.onResponse(
@@ -216,29 +203,24 @@ public void onFailure(Exception e) {
216203
);
217204
}
218205

219-
static IndicesAliasesClusterStateUpdateRequest prepareRolloverAliasesUpdateRequest(String oldIndex, String newIndex,
220-
RolloverRequest request) {
221-
List<AliasAction> actions = unmodifiableList(Arrays.asList(
222-
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, null),
223-
new AliasAction.Remove(oldIndex, request.getAlias())));
224-
final IndicesAliasesClusterStateUpdateRequest updateRequest = new IndicesAliasesClusterStateUpdateRequest(actions)
225-
.ackTimeout(request.ackTimeout())
226-
.masterNodeTimeout(request.masterNodeTimeout());
227-
return updateRequest;
228-
}
229-
230-
static IndicesAliasesClusterStateUpdateRequest prepareRolloverAliasesWriteIndexUpdateRequest(String oldIndex, String newIndex,
231-
RolloverRequest request) {
232-
List<AliasAction> actions = unmodifiableList(Arrays.asList(
233-
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, true),
234-
new AliasAction.Add(oldIndex, request.getAlias(), null, null, null, false)));
235-
final IndicesAliasesClusterStateUpdateRequest updateRequest = new IndicesAliasesClusterStateUpdateRequest(actions)
236-
.ackTimeout(request.ackTimeout())
237-
.masterNodeTimeout(request.masterNodeTimeout());
238-
return updateRequest;
206+
/**
207+
* Creates the alias actions to reflect the alias rollover from the old (source) index to the new (target/rolled over) index. An
208+
* alias pointing to multiple indices will have to be an explicit write index (ie. the old index alias has is_write_index set to true)
209+
* in which case, after the rollover, the new index will need to be the explicit write index.
210+
*/
211+
static List<AliasAction> rolloverAliasToNewIndex(String oldIndex, String newIndex, RolloverRequest request,
212+
boolean explicitWriteIndex) {
213+
if (explicitWriteIndex) {
214+
return unmodifiableList(Arrays.asList(
215+
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, true),
216+
new AliasAction.Add(oldIndex, request.getAlias(), null, null, null, false)));
217+
} else {
218+
return unmodifiableList(Arrays.asList(
219+
new AliasAction.Add(newIndex, request.getAlias(), null, null, null, null),
220+
new AliasAction.Remove(oldIndex, request.getAlias())));
221+
}
239222
}
240223

241-
242224
static String generateRolloverIndexName(String sourceIndexName, IndexNameExpressionResolver indexNameExpressionResolver) {
243225
String resolvedName = indexNameExpressionResolver.resolveDateMathExpression(sourceIndexName);
244226
final boolean isDateMath = sourceIndexName.equals(resolvedName) == false;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public void onFailure(String source, Exception e) {
258258
* Handles the cluster state transition to a version that reflects the {@link CreateIndexClusterStateUpdateRequest}.
259259
* All the requested changes are firstly validated before mutating the {@link ClusterState}.
260260
*/
261-
ClusterState applyCreateIndexRequest(ClusterState currentState, CreateIndexClusterStateUpdateRequest request) throws Exception {
261+
public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateIndexClusterStateUpdateRequest request) throws Exception {
262262
logger.trace("executing IndexCreationTask for [{}] against cluster state version [{}]", request, currentState.version());
263263
Index createdIndex = null;
264264
String removalExtraInfo = null;

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,15 @@ protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
8585

8686
@Override
8787
public ClusterState execute(ClusterState currentState) {
88-
return innerExecute(currentState, request.actions());
88+
return applyAliasActions(currentState, request.actions());
8989
}
9090
});
9191
}
9292

93-
ClusterState innerExecute(ClusterState currentState, Iterable<AliasAction> actions) {
93+
/**
94+
* Handles the cluster state transition to a version that reflects the provided {@link AliasAction}s.
95+
*/
96+
public ClusterState applyAliasActions(ClusterState currentState, Iterable<AliasAction> actions) {
9497
List<Index> indicesToClose = new ArrayList<>();
9598
Map<String, IndexService> indices = new HashMap<>();
9699
try {

server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.elasticsearch.Version;
2323
import org.elasticsearch.action.ActionListener;
2424
import org.elasticsearch.action.ActionRequest;
25-
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesClusterStateUpdateRequest;
2625
import org.elasticsearch.action.admin.indices.create.CreateIndexClusterStateUpdateRequest;
2726
import org.elasticsearch.action.admin.indices.stats.CommonStats;
2827
import org.elasticsearch.action.admin.indices.stats.IndexStats;
@@ -219,15 +218,13 @@ public void testEvaluateWithoutMetaData() {
219218
results2.forEach((k, v) -> assertFalse(v));
220219
}
221220

222-
public void testCreateUpdateAliasRequest() {
221+
public void testRolloverAliasActions() {
223222
String sourceAlias = randomAlphaOfLength(10);
224223
String sourceIndex = randomAlphaOfLength(10);
225224
String targetIndex = randomAlphaOfLength(10);
226225
final RolloverRequest rolloverRequest = new RolloverRequest(sourceAlias, targetIndex);
227-
final IndicesAliasesClusterStateUpdateRequest updateRequest =
228-
TransportRolloverAction.prepareRolloverAliasesUpdateRequest(sourceIndex, targetIndex, rolloverRequest);
229226

230-
List<AliasAction> actions = updateRequest.actions();
227+
List<AliasAction> actions = TransportRolloverAction.rolloverAliasToNewIndex(sourceIndex, targetIndex, rolloverRequest, false);
231228
assertThat(actions, hasSize(2));
232229
boolean foundAdd = false;
233230
boolean foundRemove = false;
@@ -246,15 +243,13 @@ public void testCreateUpdateAliasRequest() {
246243
assertTrue(foundRemove);
247244
}
248245

249-
public void testCreateUpdateAliasRequestWithExplicitWriteIndex() {
246+
public void testRolloverAliasActionsWithExplicitWriteIndex() {
250247
String sourceAlias = randomAlphaOfLength(10);
251248
String sourceIndex = randomAlphaOfLength(10);
252249
String targetIndex = randomAlphaOfLength(10);
253250
final RolloverRequest rolloverRequest = new RolloverRequest(sourceAlias, targetIndex);
254-
final IndicesAliasesClusterStateUpdateRequest updateRequest =
255-
TransportRolloverAction.prepareRolloverAliasesWriteIndexUpdateRequest(sourceIndex, targetIndex, rolloverRequest);
251+
List<AliasAction> actions = TransportRolloverAction.rolloverAliasToNewIndex(sourceIndex, targetIndex, rolloverRequest, true);
256252

257-
List<AliasAction> actions = updateRequest.actions();
258253
assertThat(actions, hasSize(2));
259254
boolean foundAddWrite = false;
260255
boolean foundRemoveWrite = false;

0 commit comments

Comments
 (0)