From f3aca415cd4962929177f763c9d399d1671d9f4c Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Wed, 4 Mar 2026 12:31:44 +0000 Subject: [PATCH 1/3] Return sentinel values from GET calls when sequence numbers are disabled The _seq_no and _primary_term fields will return -1 for all GET and MGET calls, making it clearer that these fields are not available for searching or versioning when sequence numbers have been disabled at the index level. --- .../org/elasticsearch/get/GetActionIT.java | 28 ++++++++++++++++ .../elasticsearch/index/engine/Engine.java | 5 +-- .../index/engine/InternalEngineTests.java | 33 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java index 027ceb4b6064f..e5ad4fdf463f8 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java @@ -26,6 +26,7 @@ import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.broadcast.BroadcastResponse; +import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.common.Randomness; import org.elasticsearch.common.Strings; import org.elasticsearch.common.bytes.BytesReference; @@ -38,6 +39,7 @@ import org.elasticsearch.index.engine.EngineTestCase; import org.elasticsearch.index.engine.VersionConflictEngineException; import org.elasticsearch.index.mapper.SourceFieldMapper; +import org.elasticsearch.index.seqno.SequenceNumbers; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.test.ESIntegTestCase; @@ -1099,6 +1101,32 @@ private GetResponse multiGetDocument(String index, String docId, String field, @ return multiGetResponse.getResponses()[0].getResponse(); } + public void testGetWithSequenceNumbersDisabled() { + assumeTrue("Test should only run with feature flag", IndexSettings.DISABLE_SEQUENCE_NUMBERS_FEATURE_FLAG); + String index = "test-seq-no-disabled"; + assertAcked( + prepareCreate(index).setSettings( + Settings.builder() + .put(IndexSettings.DISABLE_SEQUENCE_NUMBERS.getKey(), true) + .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) + .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) + ) + ); + client().prepareIndex(index).setId("1").setSource("field", "value").get(); + + GetResponse getResponse = client().prepareGet(index, "1").get(); + assertTrue(getResponse.isExists()); + assertThat(getResponse.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); + assertThat(getResponse.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); + + MultiGetResponse multiGetResponse = client().prepareMultiGet().add(index, "1").get(); + assertThat(multiGetResponse.getResponses().length, equalTo(1)); + GetResponse mgetResponse = multiGetResponse.getResponses()[0].getResponse(); + assertTrue(mgetResponse.isExists()); + assertThat(mgetResponse.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); + assertThat(mgetResponse.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); + } + private GetResponse getDocument(String index, String docId, String field, @Nullable String routing) { return getDocument(index, docId, r -> { r.setStoredFields(field); diff --git a/server/src/main/java/org/elasticsearch/index/engine/Engine.java b/server/src/main/java/org/elasticsearch/index/engine/Engine.java index 66c874a0b7a0a..f6cb3aa09144d 100644 --- a/server/src/main/java/org/elasticsearch/index/engine/Engine.java +++ b/server/src/main/java/org/elasticsearch/index/engine/Engine.java @@ -912,12 +912,13 @@ public NoOpResult(long term, long seqNo) { } protected final GetResult getFromSearcher(Get get, Engine.Searcher searcher, boolean uncachedLookup) throws EngineException { + final boolean loadSeqNo = engineConfig.getIndexSettings().sequenceNumbersDisabled() == false; final DocIdAndVersion docIdAndVersion; try { if (uncachedLookup) { - docIdAndVersion = VersionsAndSeqNoResolver.loadDocIdAndVersionUncached(searcher.getIndexReader(), get.uid(), true); + docIdAndVersion = VersionsAndSeqNoResolver.loadDocIdAndVersionUncached(searcher.getIndexReader(), get.uid(), loadSeqNo); } else { - docIdAndVersion = VersionsAndSeqNoResolver.timeSeriesLoadDocIdAndVersion(searcher.getIndexReader(), get.uid(), true); + docIdAndVersion = VersionsAndSeqNoResolver.timeSeriesLoadDocIdAndVersion(searcher.getIndexReader(), get.uid(), loadSeqNo); } } catch (Exception e) { Releasables.closeWhileHandlingException(searcher); diff --git a/server/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java b/server/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java index 950ea1695f456..6c4d572028770 100644 --- a/server/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java +++ b/server/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java @@ -7767,6 +7767,39 @@ private static void assertCommitGenerations(List commits, List commits, long generation) { var releasable = commits.keySet().stream().filter(c -> c.getGeneration() == generation).findFirst(); assertThat(releasable, isPresent()); From 034dfa8d2de3508702a4b789f7a2f189a6ccf8fc Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Wed, 4 Mar 2026 13:51:13 +0000 Subject: [PATCH 2/3] test deef --- .../java/org/elasticsearch/get/GetActionIT.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java index e5ad4fdf463f8..023051b1aa2ce 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java @@ -1112,9 +1112,12 @@ public void testGetWithSequenceNumbersDisabled() { .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) ) ); - client().prepareIndex(index).setId("1").setSource("field", "value").get(); + client().prepareIndex(index).setId("1") + .setRefreshPolicy(randomFrom(WriteRequest.RefreshPolicy.values())) + .setSource("field", "value") + .get(); - GetResponse getResponse = client().prepareGet(index, "1").get(); + GetResponse getResponse = client().prepareGet(index, "1").setRealtime(randomBoolean()).get(); assertTrue(getResponse.isExists()); assertThat(getResponse.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); assertThat(getResponse.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); From f90891bde301bf0e3132fe2f6ce50912257251ba Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Wed, 4 Mar 2026 15:03:08 +0000 Subject: [PATCH 3/3] make test more explicit --- .../org/elasticsearch/get/GetActionIT.java | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java index 023051b1aa2ce..3c7b08614ffde 100644 --- a/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java +++ b/server/src/internalClusterTest/java/org/elasticsearch/get/GetActionIT.java @@ -1108,26 +1108,58 @@ public void testGetWithSequenceNumbersDisabled() { prepareCreate(index).setSettings( Settings.builder() .put(IndexSettings.DISABLE_SEQUENCE_NUMBERS.getKey(), true) + .put("index.refresh_interval", -1) .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0) ) ); - client().prepareIndex(index).setId("1") - .setRefreshPolicy(randomFrom(WriteRequest.RefreshPolicy.values())) - .setSource("field", "value") - .get(); - GetResponse getResponse = client().prepareGet(index, "1").setRealtime(randomBoolean()).get(); - assertTrue(getResponse.isExists()); - assertThat(getResponse.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); - assertThat(getResponse.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); + prepareIndex(index).setId("1").setSource("field", "value1").get(); + prepareIndex(index).setId("2").setSource("field", "value2").get(); + prepareIndex(index).setId("3").setSource("field", "value3").get(); - MultiGetResponse multiGetResponse = client().prepareMultiGet().add(index, "1").get(); - assertThat(multiGetResponse.getResponses().length, equalTo(1)); - GetResponse mgetResponse = multiGetResponse.getResponses()[0].getResponse(); - assertTrue(mgetResponse.isExists()); - assertThat(mgetResponse.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); - assertThat(mgetResponse.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); + assertSeqNoDisabledGet(client().prepareGet(index, "1").get()); + assertSeqNoDisabledGet(client().prepareGet(index, "2").get()); + + MultiGetResponse mgetResponse = client().prepareMultiGet().add(index, "1").add(index, "2").add(index, "3").get(); + assertThat(mgetResponse.getResponses().length, equalTo(3)); + for (MultiGetItemResponse item : mgetResponse.getResponses()) { + assertSeqNoDisabledGet(item.getResponse()); + } + + refresh(index); + + assertSeqNoDisabledGet(client().prepareGet(index, "1").get()); + assertSeqNoDisabledGet(client().prepareGet(index, "2").setRealtime(false).get()); + + mgetResponse = client().prepareMultiGet().add(index, "1").add(index, "2").add(index, "3").get(); + for (MultiGetItemResponse item : mgetResponse.getResponses()) { + assertSeqNoDisabledGet(item.getResponse()); + } + + prepareIndex(index).setId("4").setSource("field", "value4").get(); + assertSeqNoDisabledGet(client().prepareGet(index, "4").get()); + + flush(index); + + assertSeqNoDisabledGet(client().prepareGet(index, "1").get()); + assertSeqNoDisabledGet(client().prepareGet(index, "3").setRealtime(false).get()); + assertSeqNoDisabledGet(client().prepareGet(index, "4").get()); + + mgetResponse = client().prepareMultiGet().add(index, "1").add(index, "2").add(index, "3").add(index, "4").get(); + assertThat(mgetResponse.getResponses().length, equalTo(4)); + for (MultiGetItemResponse item : mgetResponse.getResponses()) { + assertSeqNoDisabledGet(item.getResponse()); + } + + prepareIndex(index).setId("1").setSource("field", "value1_updated").get(); + assertSeqNoDisabledGet(client().prepareGet(index, "1").get()); + } + + private static void assertSeqNoDisabledGet(GetResponse response) { + assertTrue(response.isExists()); + assertThat(response.getSeqNo(), equalTo(SequenceNumbers.UNASSIGNED_SEQ_NO)); + assertThat(response.getPrimaryTerm(), equalTo(SequenceNumbers.UNASSIGNED_PRIMARY_TERM)); } private GetResponse getDocument(String index, String docId, String field, @Nullable String routing) {