Skip to content

Commit ac0cf95

Browse files
authored
Rework ShardSearchContextId to explain use of searcher id better (#135233)
When a ShardSearchContextId has a searcher id, this indicates that the searcher backing the context is stable so we can retry a shard on a different node if the original context is gone (e.g. due to node restarts). We use the searcher ids only for PIT contexts and only if the underlying engine supports it (e.g. currently only FrozenEngine and ReadOnlyEngine). This change moves the related decision logic into ShardSearchContextId itself because there is no need to expose the search id once its set. By renaming the access methods we can also communicate the intended use of these ids better.
1 parent 5a15fa9 commit ac0cf95

File tree

5 files changed

+22
-17
lines changed

5 files changed

+22
-17
lines changed

server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import org.elasticsearch.search.builder.SearchSourceBuilder;
8282
import org.elasticsearch.search.internal.AliasFilter;
8383
import org.elasticsearch.search.internal.SearchContext;
84+
import org.elasticsearch.search.internal.ShardSearchContextId;
8485
import org.elasticsearch.search.profile.SearchProfileResults;
8586
import org.elasticsearch.search.profile.SearchProfileShardResult;
8687
import org.elasticsearch.tasks.Task;
@@ -1271,7 +1272,8 @@ static List<SearchShardIterator> getRemoteShardsIteratorFromPointInTime(
12711272
// Otherwise, we add the shard iterator without a target node, allowing a partial search failure to
12721273
// be thrown when a search phase attempts to access it.
12731274
targetNodes.add(perNode.getNode());
1274-
if (perNode.getSearchContextId().getSearcherId() != null) {
1275+
ShardSearchContextId shardSearchContextId = perNode.getSearchContextId();
1276+
if (shardSearchContextId != null && shardSearchContextId.isRetryable()) {
12751277
for (String node : group.allocatedNodes()) {
12761278
if (node.equals(perNode.getNode()) == false) {
12771279
targetNodes.add(node);
@@ -1947,7 +1949,8 @@ static List<SearchShardIterator> getLocalShardsIteratorFromPointInTime(
19471949
if (projectState.cluster().nodes().nodeExists(perNode.getNode())) {
19481950
targetNodes.add(perNode.getNode());
19491951
}
1950-
if (perNode.getSearchContextId().getSearcherId() != null) {
1952+
ShardSearchContextId shardSearchContextId = perNode.getSearchContextId();
1953+
if (shardSearchContextId.isRetryable()) {
19511954
for (ShardRouting shard : shards) {
19521955
if (shard.currentNodeId().equals(perNode.getNode()) == false) {
19531956
targetNodes.add(shard.currentNodeId());

server/src/main/java/org/elasticsearch/search/SearchService.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,18 +1264,18 @@ private ReaderContext findReaderContext(ShardSearchContextId id, TransportReques
12641264
}
12651265

12661266
final ReaderContext createOrGetReaderContext(ShardSearchRequest request) {
1267+
ShardSearchContextId readerId = request.readerId();
12671268
if (request.readerId() != null) {
12681269
try {
1269-
return findReaderContext(request.readerId(), request);
1270+
return findReaderContext(readerId, request);
12701271
} catch (SearchContextMissingException e) {
1271-
final String searcherId = request.readerId().getSearcherId();
1272-
if (searcherId == null) {
1272+
if (readerId.isRetryable() == false) {
12731273
throw e;
12741274
}
12751275
final IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex());
12761276
final IndexShard shard = indexService.getShard(request.shardId().id());
12771277
final Engine.SearcherSupplier searcherSupplier = shard.acquireSearcherSupplier();
1278-
if (searcherId.equals(searcherSupplier.getSearcherId()) == false) {
1278+
if (readerId.sameSearcherIdsAs(searcherSupplier.getSearcherId()) == false) {
12791279
searcherSupplier.close();
12801280
throw e;
12811281
}
@@ -1298,8 +1298,8 @@ final ReaderContext createAndPutReaderContext(
12981298
ReaderContext readerContext = null;
12991299
Releasable decreaseScrollContexts = null;
13001300
try {
1301-
final ShardSearchContextId id = new ShardSearchContextId(sessionId, idGenerator.incrementAndGet());
13021301
if (request.scroll() != null) {
1302+
final ShardSearchContextId id = new ShardSearchContextId(sessionId, idGenerator.incrementAndGet());
13031303
decreaseScrollContexts = openScrollContexts::decrementAndGet;
13041304
if (openScrollContexts.incrementAndGet() > maxOpenScrollContext) {
13051305
throw new TooManyScrollContextsException(maxOpenScrollContext, MAX_OPEN_SCROLL_CONTEXT.getKey());
@@ -1308,6 +1308,7 @@ final ReaderContext createAndPutReaderContext(
13081308
readerContext.addOnClose(decreaseScrollContexts);
13091309
decreaseScrollContexts = null;
13101310
} else {
1311+
final ShardSearchContextId id = new ShardSearchContextId(sessionId, idGenerator.incrementAndGet(), reader.getSearcherId());
13111312
readerContext = new ReaderContext(id, indexService, shard, reader, keepAliveInMillis, true);
13121313
}
13131314
reader = null;
@@ -1399,7 +1400,7 @@ public SearchContext createSearchContext(ShardSearchRequest request, TimeValue t
13991400
final IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex());
14001401
final IndexShard indexShard = indexService.getShard(request.shardId().getId());
14011402
final Engine.SearcherSupplier reader = indexShard.acquireSearcherSupplier();
1402-
final ShardSearchContextId id = new ShardSearchContextId(sessionId, idGenerator.incrementAndGet());
1403+
final ShardSearchContextId id = new ShardSearchContextId(sessionId, idGenerator.incrementAndGet(), reader.getSearcherId());
14031404
try (ReaderContext readerContext = new ReaderContext(id, indexService, indexShard, reader, -1L, true)) {
14041405
DefaultSearchContext searchContext = createSearchContext(readerContext, request, timeout, ResultsType.NONE);
14051406
searchContext.addReleasable(readerContext.markAsUsed(0L));
@@ -2037,8 +2038,7 @@ static CanMatchShardResponse canMatch(CanMatchContext canMatchContext, boolean c
20372038
}
20382039
searcher = readerContext.acquireSearcher(Engine.CAN_MATCH_SEARCH_SOURCE);
20392040
} catch (SearchContextMissingException e) {
2040-
final String searcherId = canMatchContext.request.readerId().getSearcherId();
2041-
if (searcherId == null) {
2041+
if (canMatchContext.request.readerId().isRetryable() == false) {
20422042
return new CanMatchShardResponse(true, null);
20432043
}
20442044
if (queryStillMatchesAfterRewrite(
@@ -2048,7 +2048,7 @@ static CanMatchShardResponse canMatch(CanMatchContext canMatchContext, boolean c
20482048
return new CanMatchShardResponse(false, null);
20492049
}
20502050
final Engine.SearcherSupplier searcherSupplier = canMatchContext.getShard().acquireSearcherSupplier();
2051-
if (searcherId.equals(searcherSupplier.getSearcherId()) == false) {
2051+
if (canMatchContext.request.readerId().sameSearcherIdsAs(searcherSupplier.getSearcherId()) == false) {
20522052
searcherSupplier.close();
20532053
return new CanMatchShardResponse(true, null);
20542054
}

server/src/main/java/org/elasticsearch/search/internal/LegacyReaderContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public LegacyReaderContext(
3636
super(id, indexService, indexShard, reader, keepAliveInMillis, false);
3737
assert shardSearchRequest.readerId() == null;
3838
assert shardSearchRequest.keepAlive() == null;
39-
assert id.getSearcherId() == null : "Legacy reader context must not have searcher id";
39+
assert id.isRetryable() == false : "Legacy reader context is not retryable";
4040
this.shardSearchRequest = Objects.requireNonNull(shardSearchRequest, "ShardSearchRequest must be provided");
4141
if (shardSearchRequest.scroll() != null) {
4242
// Search scroll requests are special, they don't hold indices names so we have

server/src/main/java/org/elasticsearch/search/internal/ShardSearchContextId.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ public final class ShardSearchContextId implements Writeable {
2121
private final long id;
2222
private final String searcherId;
2323

24-
// TODO: Remove this constructor
2524
public ShardSearchContextId(String sessionId, long id) {
2625
this(sessionId, id, null);
2726
}
@@ -43,7 +42,6 @@ public void writeTo(StreamOutput out) throws IOException {
4342
out.writeLong(id);
4443
out.writeString(sessionId);
4544
out.writeOptionalString(searcherId);
46-
4745
}
4846

4947
public String getSessionId() {
@@ -54,8 +52,12 @@ public long getId() {
5452
return id;
5553
}
5654

57-
public String getSearcherId() {
58-
return searcherId;
55+
public boolean isRetryable() {
56+
return this.searcherId != null;
57+
}
58+
59+
public boolean sameSearcherIdsAs(String otherSearcherId) {
60+
return this.isRetryable() && this.searcherId.equals(otherSearcherId);
5961
}
6062

6163
@Override

server/src/test/java/org/elasticsearch/action/search/TransportSearchActionTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1702,7 +1702,7 @@ public void testLocalShardIteratorFromPointInTime() {
17021702
final ShardId shardId = new ShardId(indexMetadata.getIndex(), id);
17031703
final SearchShardIterator shardIterator = shardIterators.get(id);
17041704
final SearchContextIdForNode context = contexts.get(shardId);
1705-
if (context.getSearchContextId().getSearcherId() == null) {
1705+
if (context.getSearchContextId().isRetryable() == false) {
17061706
assertThat(shardIterator.getTargetNodeIds(), hasSize(1));
17071707
} else {
17081708
final List<String> targetNodes = clusterState.routingTable(project)

0 commit comments

Comments
 (0)