Skip to content

Commit 6851803

Browse files
authored
Don't fail delete index API if an index is deleted during the request (#138015)
In some cases, an index may have already been deleted by the time we process the deletion cluster state update task. In that case, we can simply skip it instead of throwing an exception. Index name resolution will have failed in the transport action (or in security) if the index never existed. Closes #137422
1 parent 6aa1eb4 commit 6851803

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

docs/changelog/138015.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 138015
2+
summary: Don't fail delete index API if an index is deleted during the request
3+
area: Indices APIs
4+
type: bug
5+
issues:
6+
- 137422

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.delete/10_basic.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,9 @@ setup:
9898
index: index,index2
9999
- is_true: index
100100
- is_true: index2
101+
---
102+
"Delete nonexistent concrete index":
103+
- do:
104+
catch: missing
105+
indices.delete:
106+
index: nonexistent_index

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.util.HashSet;
4242
import java.util.Map;
4343
import java.util.Objects;
44+
import java.util.Optional;
4445
import java.util.Set;
4546

4647
import static org.elasticsearch.cluster.routing.allocation.allocator.AllocationActionListener.rerouteCompletionIsNotRequired;
@@ -145,8 +146,15 @@ public void onFailure(Exception e) {
145146
public static ClusterState deleteIndices(ClusterState clusterState, Set<Index> indices, Settings settings) {
146147
final Map<ProjectId, Set<Index>> byProject = new HashMap<>();
147148
for (Index index : indices) {
148-
final ProjectMetadata project = clusterState.metadata().projectFor(index);
149-
byProject.computeIfAbsent(project.id(), ignore -> new HashSet<>()).add(index);
149+
final Optional<ProjectMetadata> project = clusterState.metadata().lookupProject(index);
150+
// In some cases, the index may have already been deleted by the time we process the deletion task. For example, if multiple
151+
// delete requests are made concurrently for the same index (or a wildcard), and they all resolve the index and then run this
152+
// cluster state update task. In that case, we can simply skip it. Index name resolution will have failed in the transport
153+
// action (or in security) if the index never existed.
154+
if (project.isEmpty()) {
155+
continue;
156+
}
157+
byProject.computeIfAbsent(project.get().id(), ignore -> new HashSet<>()).add(index);
150158
}
151159

152160
for (final Map.Entry<ProjectId, Set<Index>> entry : byProject.entrySet()) {

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.elasticsearch.common.util.concurrent.DeterministicTaskQueue;
2323
import org.elasticsearch.core.Tuple;
2424
import org.elasticsearch.index.Index;
25-
import org.elasticsearch.index.IndexNotFoundException;
2625
import org.elasticsearch.index.IndexVersion;
2726
import org.elasticsearch.repositories.IndexId;
2827
import org.elasticsearch.snapshots.Snapshot;
@@ -78,12 +77,9 @@ public void setUp() throws Exception {
7877

7978
public void testDeleteMissing() {
8079
Index index = new Index("missing", "doesn't matter");
81-
ClusterState state = ClusterState.builder(ClusterName.DEFAULT).build();
82-
IndexNotFoundException e = expectThrows(
83-
IndexNotFoundException.class,
84-
() -> MetadataDeleteIndexService.deleteIndices(state, Set.of(index), Settings.EMPTY)
85-
);
86-
assertEquals(index, e.getIndex());
80+
ClusterState before = ClusterState.builder(ClusterName.DEFAULT).build();
81+
ClusterState after = MetadataDeleteIndexService.deleteIndices(before, Set.of(index), Settings.EMPTY);
82+
assertSame(before, after);
8783
}
8884

8985
public void testDeleteSnapshotting() {

0 commit comments

Comments
 (0)