diff --git a/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java index d56d7471d498e..7fecc53826ff1 100644 --- a/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/server/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -4491,14 +4491,17 @@ public void waitForEngineOrClosedShard(ActionListener listener) { } /** - * Registers a listener for an event when the shard advances to the provided primary term and segment generation + * Registers a listener for an event when the shard advances to the provided primary term and segment generation. + * Completes the listener with a {@link IndexShardClosedException} if the shard is closed. */ public void waitForPrimaryTermAndGeneration(long primaryTerm, long segmentGeneration, ActionListener listener) { - waitForEngineOrClosedShard( - listener.delegateFailureAndWrap( - (l, ignored) -> getEngine().addPrimaryTermAndGenerationListener(primaryTerm, segmentGeneration, l) - ) - ); + waitForEngineOrClosedShard(listener.delegateFailureAndWrap((l, ignored) -> { + if (state == IndexShardState.CLOSED) { + l.onFailure(new IndexShardClosedException(shardId)); + } else { + getEngine().addPrimaryTermAndGenerationListener(primaryTerm, segmentGeneration, l); + } + })); } /** diff --git a/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java b/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java index c07b396626c45..975565b73a0d6 100644 --- a/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java +++ b/server/src/test/java/org/elasticsearch/index/shard/IndexShardTests.java @@ -27,6 +27,7 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.Constants; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; @@ -3334,6 +3335,21 @@ public void testWaitForClosedListener() throws IOException { assertThat("listener should have been called", called.get(), equalTo(true)); } + public void testWaitForPrimaryTermAndGenerationFailsForClosedShard() throws IOException { + Settings settings = indexSettings(IndexVersion.current(), 1, 1).build(); + IndexMetadata metadata = IndexMetadata.builder("test").putMapping(""" + { "properties": { "foo": { "type": "text"}}}""").settings(settings).primaryTerm(0, 1).build(); + IndexShard initializingShard = newShard(new ShardId(metadata.getIndex(), 0), true, "n1", metadata, null); + + var future = new PlainActionFuture(); + initializingShard.waitForPrimaryTermAndGeneration(0L, 0L, future); + + assertFalse("waitForPrimaryTermAndGeneration should be waiting", future.isDone()); + closeShards(initializingShard); + // Should bail out earlier without calling the engine + assertNotNull(ExceptionsHelper.unwrap(expectThrows(Exception.class, future::get), IndexShardClosedException.class)); + } + public void testRecoverFromLocalShard() throws IOException { Settings settings = indexSettings(IndexVersion.current(), 1, 1).build(); IndexMetadata metadata = IndexMetadata.builder("source")