Skip to content

Commit a0c504e

Browse files
authored
Create specific exception for when snapshots are in progress (elastic#37550)
delete and close index actions threw IllegalArgumentExceptions when attempting to run against an index that has a snapshot in progress. This change introduces a dedicated SnapshotInProgressException for these scenarios. This is done to explicitly signal to clients that this is the reason the action failed, and it is a retryable error. relates to elastic#37541.
1 parent 5782a5b commit a0c504e

File tree

7 files changed

+60
-7
lines changed

7 files changed

+60
-7
lines changed

server/src/main/java/org/elasticsearch/ElasticsearchException.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,9 @@ private enum ElasticsearchExceptionHandle {
10101010
COORDINATION_STATE_REJECTED_EXCEPTION(org.elasticsearch.cluster.coordination.CoordinationStateRejectedException.class,
10111011
org.elasticsearch.cluster.coordination.CoordinationStateRejectedException::new, 150, Version.V_7_0_0),
10121012
CLUSTER_ALREADY_BOOTSTRAPPED_EXCEPTION(org.elasticsearch.cluster.coordination.ClusterAlreadyBootstrappedException.class,
1013-
org.elasticsearch.cluster.coordination.ClusterAlreadyBootstrappedException::new, 151, Version.V_7_0_0);
1013+
org.elasticsearch.cluster.coordination.ClusterAlreadyBootstrappedException::new, 151, Version.V_7_0_0),
1014+
SNAPSHOT_IN_PROGRESS_EXCEPTION(org.elasticsearch.snapshots.SnapshotInProgressException.class,
1015+
org.elasticsearch.snapshots.SnapshotInProgressException::new, 152, Version.V_7_0_0);
10141016

10151017
final Class<? extends ElasticsearchException> exceptionClass;
10161018
final CheckedFunction<StreamInput, ? extends ElasticsearchException, IOException> constructor;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.snapshots;
21+
22+
import org.elasticsearch.ElasticsearchException;
23+
import org.elasticsearch.common.io.stream.StreamInput;
24+
import org.elasticsearch.rest.RestStatus;
25+
26+
import java.io.IOException;
27+
28+
/**
29+
* Thrown on the attempt to execute an action that requires
30+
* that no snapshot is in progress.
31+
*/
32+
public class SnapshotInProgressException extends ElasticsearchException {
33+
34+
public SnapshotInProgressException(String msg) {
35+
super(msg);
36+
}
37+
38+
public SnapshotInProgressException(StreamInput in) throws IOException {
39+
super(in);
40+
}
41+
42+
@Override
43+
public RestStatus status() {
44+
return RestStatus.BAD_REQUEST;
45+
}
46+
}
47+

server/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ private ImmutableOpenMap<ShardId, SnapshotsInProgress.ShardSnapshotStatus> shard
14471447
public static void checkIndexDeletion(ClusterState currentState, Set<IndexMetaData> indices) {
14481448
Set<Index> indicesToFail = indicesToFailForCloseOrDeletion(currentState, indices);
14491449
if (indicesToFail != null) {
1450-
throw new IllegalArgumentException("Cannot delete indices that are being snapshotted: " + indicesToFail +
1450+
throw new SnapshotInProgressException("Cannot delete indices that are being snapshotted: " + indicesToFail +
14511451
". Try again after snapshot finishes or cancel the currently running snapshot.");
14521452
}
14531453
}
@@ -1459,7 +1459,7 @@ public static void checkIndexDeletion(ClusterState currentState, Set<IndexMetaDa
14591459
public static void checkIndexClosing(ClusterState currentState, Set<IndexMetaData> indices) {
14601460
Set<Index> indicesToFail = indicesToFailForCloseOrDeletion(currentState, indices);
14611461
if (indicesToFail != null) {
1462-
throw new IllegalArgumentException("Cannot close indices that are being snapshotted: " + indicesToFail +
1462+
throw new SnapshotInProgressException("Cannot close indices that are being snapshotted: " + indicesToFail +
14631463
". Try again after snapshot finishes or cancel the currently running snapshot.");
14641464
}
14651465
}

server/src/test/java/org/elasticsearch/ExceptionSerializationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
import org.elasticsearch.snapshots.Snapshot;
8080
import org.elasticsearch.snapshots.SnapshotException;
8181
import org.elasticsearch.snapshots.SnapshotId;
82+
import org.elasticsearch.snapshots.SnapshotInProgressException;
8283
import org.elasticsearch.test.ESTestCase;
8384
import org.elasticsearch.test.TestSearchContext;
8485
import org.elasticsearch.test.VersionUtils;
@@ -809,6 +810,7 @@ public void testIds() {
809810
ids.put(149, MultiBucketConsumerService.TooManyBucketsException.class);
810811
ids.put(150, CoordinationStateRejectedException.class);
811812
ids.put(151, ClusterAlreadyBootstrappedException.class);
813+
ids.put(152, SnapshotInProgressException.class);
812814

813815
Map<Class<? extends ElasticsearchException>, Integer> reverse = new HashMap<>();
814816
for (Map.Entry<Integer, Class<? extends ElasticsearchException>> entry : ids.entrySet()) {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.elasticsearch.repositories.IndexId;
3333
import org.elasticsearch.snapshots.Snapshot;
3434
import org.elasticsearch.snapshots.SnapshotId;
35+
import org.elasticsearch.snapshots.SnapshotInProgressException;
3536
import org.elasticsearch.test.ESTestCase;
3637
import org.elasticsearch.test.VersionUtils;
3738

@@ -63,7 +64,7 @@ SnapshotsInProgress.State.INIT, singletonList(new IndexId(index, "doesn't matter
6364
ClusterState state = ClusterState.builder(clusterState(index))
6465
.putCustom(SnapshotsInProgress.TYPE, snaps)
6566
.build();
66-
Exception e = expectThrows(IllegalArgumentException.class,
67+
Exception e = expectThrows(SnapshotInProgressException.class,
6768
() -> service.deleteIndices(state, singleton(state.metaData().getIndices().get(index).getIndex())));
6869
assertEquals("Cannot delete indices that are being snapshotted: [[" + index + "]]. Try again after snapshot finishes "
6970
+ "or cancel the currently running snapshot.", e.getMessage());

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.elasticsearch.repositories.IndexId;
4747
import org.elasticsearch.snapshots.Snapshot;
4848
import org.elasticsearch.snapshots.SnapshotId;
49+
import org.elasticsearch.snapshots.SnapshotInProgressException;
4950
import org.elasticsearch.test.ESTestCase;
5051

5152
import java.util.Arrays;
@@ -171,7 +172,7 @@ public void testAddIndexClosedBlocks() {
171172
assertThat(exception.getMessage(), containsString("Cannot close indices that are being restored: [[restored]]"));
172173
}
173174
{
174-
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> {
175+
SnapshotInProgressException exception = expectThrows(SnapshotInProgressException.class, () -> {
175176
ClusterState state = addSnapshotIndex("snapshotted", randomIntBetween(1, 3), randomIntBetween(0, 3), initialState);
176177
if (randomBoolean()) {
177178
state = addOpenedIndex("opened", randomIntBetween(1, 3), randomIntBetween(0, 3), state);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,15 +2492,15 @@ public void testCloseOrDeleteIndexDuringSnapshot() throws Exception {
24922492
logger.info("--> delete index while non-partial snapshot is running");
24932493
client.admin().indices().prepareDelete("test-idx-1").get();
24942494
fail("Expected deleting index to fail during snapshot");
2495-
} catch (IllegalArgumentException e) {
2495+
} catch (SnapshotInProgressException e) {
24962496
assertThat(e.getMessage(), containsString("Cannot delete indices that are being snapshotted: [[test-idx-1/"));
24972497
}
24982498
} else {
24992499
try {
25002500
logger.info("--> close index while non-partial snapshot is running");
25012501
client.admin().indices().prepareClose("test-idx-1").get();
25022502
fail("Expected closing index to fail during snapshot");
2503-
} catch (IllegalArgumentException e) {
2503+
} catch (SnapshotInProgressException e) {
25042504
assertThat(e.getMessage(), containsString("Cannot close indices that are being snapshotted: [[test-idx-1/"));
25052505
}
25062506
}

0 commit comments

Comments
 (0)