Skip to content

Commit f6d7d53

Browse files
committed
Enforce max_buckets limit only in the final reduction phase (#36152)
Given that we check the max buckets limit on each shard when collecting the buckets, and that non final reduction cannot add buckets (see #35921), there is no point in counting and checking the number of buckets as part of non final reduction phases. Such check is still needed though in the final reduction phases to make sure that the number of returned buckets is not above the allowed threshold. Relates somehow to #32125 as we will make use of non final reduction phases in CCS alternate execution mode and that increases the chance that this check trips for nothing when reducing aggs in each remote cluster.
1 parent 902a3e1 commit f6d7d53

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1090,7 +1090,8 @@ public QueryRewriteContext getRewriteContext(LongSupplier nowInMillis) {
10901090
}
10911091

10921092
public InternalAggregation.ReduceContext createReduceContext(boolean finalReduce) {
1093-
return new InternalAggregation.ReduceContext(bigArrays, scriptService, multiBucketConsumerService.create(), finalReduce);
1093+
return new InternalAggregation.ReduceContext(bigArrays, scriptService,
1094+
finalReduce ? multiBucketConsumerService.create() : bucketCount -> {}, finalReduce);
10941095
}
10951096

10961097
public static final class CanMatchResponse extends SearchPhaseResult {

server/src/test/java/org/elasticsearch/search/SearchServiceTests.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package org.elasticsearch.search;
2020

2121
import com.carrotsearch.hppc.IntArrayList;
22-
2322
import org.apache.lucene.search.Query;
2423
import org.apache.lucene.store.AlreadyClosedException;
2524
import org.elasticsearch.action.ActionListener;
@@ -59,6 +58,8 @@
5958
import org.elasticsearch.script.MockScriptPlugin;
6059
import org.elasticsearch.script.Script;
6160
import org.elasticsearch.script.ScriptType;
61+
import org.elasticsearch.search.aggregations.InternalAggregation;
62+
import org.elasticsearch.search.aggregations.MultiBucketConsumerService;
6263
import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregationBuilder;
6364
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
6465
import org.elasticsearch.search.aggregations.support.ValueType;
@@ -152,10 +153,11 @@ public void onQueryPhase(SearchContext context, long tookInNanos) {
152153

153154
@Override
154155
protected Settings nodeSettings() {
155-
return Settings.builder().put("search.default_search_timeout", "5s").build();
156+
return Settings.builder().put("search.default_search_timeout", "5s")
157+
.put(MultiBucketConsumerService.MAX_BUCKET_SETTING.getKey(), MultiBucketConsumerService.SOFT_LIMIT_MAX_BUCKETS).build();
156158
}
157159

158-
public void testClearOnClose() throws ExecutionException, InterruptedException {
160+
public void testClearOnClose() {
159161
createIndex("index");
160162
client().prepareIndex("index", "type", "1").setSource("field", "value").setRefreshPolicy(IMMEDIATE).get();
161163
SearchResponse searchResponse = client().prepareSearch("index").setSize(1).setScroll("1m").get();
@@ -167,7 +169,7 @@ public void testClearOnClose() throws ExecutionException, InterruptedException {
167169
assertEquals(0, service.getActiveContexts());
168170
}
169171

170-
public void testClearOnStop() throws ExecutionException, InterruptedException {
172+
public void testClearOnStop() {
171173
createIndex("index");
172174
client().prepareIndex("index", "type", "1").setSource("field", "value").setRefreshPolicy(IMMEDIATE).get();
173175
SearchResponse searchResponse = client().prepareSearch("index").setSize(1).setScroll("1m").get();
@@ -179,7 +181,7 @@ public void testClearOnStop() throws ExecutionException, InterruptedException {
179181
assertEquals(0, service.getActiveContexts());
180182
}
181183

182-
public void testClearIndexDelete() throws ExecutionException, InterruptedException {
184+
public void testClearIndexDelete() {
183185
createIndex("index");
184186
client().prepareIndex("index", "type", "1").setSource("field", "value").setRefreshPolicy(IMMEDIATE).get();
185187
SearchResponse searchResponse = client().prepareSearch("index").setSize(1).setScroll("1m").get();
@@ -208,7 +210,7 @@ public void testCloseSearchContextOnRewriteException() {
208210
assertEquals(activeRefs, indexShard.store().refCount());
209211
}
210212

211-
public void testSearchWhileIndexDeleted() throws IOException, InterruptedException {
213+
public void testSearchWhileIndexDeleted() throws InterruptedException {
212214
createIndex("index");
213215
client().prepareIndex("index", "type", "1").setSource("field", "value").setRefreshPolicy(IMMEDIATE).get();
214216

@@ -443,15 +445,15 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryRewriteContext) {
443445
}
444446

445447
@Override
446-
protected void doWriteTo(StreamOutput out) throws IOException {
448+
protected void doWriteTo(StreamOutput out) {
447449
}
448450

449451
@Override
450-
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
452+
protected void doXContent(XContentBuilder builder, Params params) {
451453
}
452454

453455
@Override
454-
protected Query doToQuery(QueryShardContext context) throws IOException {
456+
protected Query doToQuery(QueryShardContext context) {
455457
return null;
456458
}
457459

@@ -501,7 +503,6 @@ public void testCanMatch() throws IOException {
501503
assertFalse(service.canMatch(new ShardSearchLocalRequest(indexShard.shardId(), 1, SearchType.QUERY_THEN_FETCH,
502504
new SearchSourceBuilder().query(new MatchNoneQueryBuilder()), Strings.EMPTY_ARRAY, false,
503505
new AliasFilter(null, Strings.EMPTY_ARRAY), 1f, allowPartialSearchResults, null, null)));
504-
505506
}
506507

507508
public void testCanRewriteToMatchNone() {
@@ -519,7 +520,6 @@ public void testCanRewriteToMatchNone() {
519520
.suggest(new SuggestBuilder())));
520521
assertFalse(SearchService.canRewriteToMatchNone(new SearchSourceBuilder().query(new TermQueryBuilder("foo", "bar"))
521522
.suggest(new SuggestBuilder())));
522-
523523
}
524524

525525
public void testSetSearchThrottled() {
@@ -568,4 +568,17 @@ public void testExpandSearchThrottled() {
568568
assertHitCount(client().prepareSearch().get(), 0L);
569569
assertHitCount(client().prepareSearch().setIndicesOptions(IndicesOptions.STRICT_EXPAND_OPEN_FORBID_CLOSED).get(), 1L);
570570
}
571+
572+
public void testCreateReduceContext() {
573+
final SearchService service = getInstanceFromNode(SearchService.class);
574+
{
575+
InternalAggregation.ReduceContext reduceContext = service.createReduceContext(true);
576+
expectThrows(MultiBucketConsumerService.TooManyBucketsException.class,
577+
() -> reduceContext.consumeBucketsAndMaybeBreak(MultiBucketConsumerService.SOFT_LIMIT_MAX_BUCKETS + 1));
578+
}
579+
{
580+
InternalAggregation.ReduceContext reduceContext = service.createReduceContext(false);
581+
reduceContext.consumeBucketsAndMaybeBreak(MultiBucketConsumerService.SOFT_LIMIT_MAX_BUCKETS + 1);
582+
}
583+
}
571584
}

0 commit comments

Comments
 (0)