@@ -91,7 +91,7 @@ public void skipOnAborted() {
9191 * This used to fail, but we've since compacted top n so it actually succeeds now.
9292 */
9393 public void testSortByManyLongsSuccess () throws IOException {
94- initManyLongs ();
94+ initManyLongs (10 );
9595 Map <String , Object > response = sortByManyLongs (500 );
9696 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ))
9797 .item (matchesMap ().entry ("name" , "b" ).entry ("type" , "long" ));
@@ -108,7 +108,7 @@ public void testSortByManyLongsSuccess() throws IOException {
108108 * This used to crash the node with an out of memory, but now it just trips a circuit breaker.
109109 */
110110 public void testSortByManyLongsTooMuchMemory () throws IOException {
111- initManyLongs ();
111+ initManyLongs (10 );
112112 // 5000 is plenty to break on most nodes
113113 assertCircuitBreaks (attempt -> sortByManyLongs (attempt * 5000 ));
114114 }
@@ -117,7 +117,7 @@ public void testSortByManyLongsTooMuchMemory() throws IOException {
117117 * This should record an async response with a {@link CircuitBreakingException}.
118118 */
119119 public void testSortByManyLongsTooMuchMemoryAsync () throws IOException {
120- initManyLongs ();
120+ initManyLongs (10 );
121121 Request request = new Request ("POST" , "/_query/async" );
122122 request .addParameter ("error_trace" , "" );
123123 request .setJsonEntity (makeSortByManyLongs (5000 ).toString ().replace ("\n " , "\\ n" ));
@@ -194,6 +194,24 @@ public void testSortByManyLongsTooMuchMemoryAsync() throws IOException {
194194 );
195195 }
196196
197+ public void testSortByManyLongsGiantTopN () throws IOException {
198+ initManyLongs (10 );
199+ assertMap (sortBySomeLongsLimit (100000 ),
200+ matchesMap ()
201+ .entry ("took" , greaterThan (0 ))
202+ .entry ("is_partial" , false )
203+ .entry ("columns" , List .of (Map .of ("name" , "MAX(a)" , "type" , "long" )))
204+ .entry ("values" , List .of (List .of (9 )))
205+ .entry ("documents_found" , greaterThan (0 ))
206+ .entry ("values_loaded" , greaterThan (0 ))
207+ );
208+ }
209+
210+ public void testSortByManyLongsGiantTopNTooMuchMemory () throws IOException {
211+ initManyLongs (20 );
212+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (attempt * 500000 ));
213+ }
214+
197215 private static final int MAX_ATTEMPTS = 5 ;
198216
199217 interface TryCircuitBreaking {
@@ -252,11 +270,25 @@ private StringBuilder makeSortByManyLongs(int count) {
252270 return query ;
253271 }
254272
273+ private Map <String , Object > sortBySomeLongsLimit (int count ) throws IOException {
274+ logger .info ("sorting by 5 longs, keeping {}" , count );
275+ return responseAsMap (query (makeSortBySomeLongsLimit (count ), null ));
276+ }
277+
278+ private String makeSortBySomeLongsLimit (int count ) {
279+ StringBuilder query = new StringBuilder ("{\" query\" : \" FROM manylongs\n " );
280+ query .append ("| SORT a, b, c, d, e\n " );
281+ query .append ("| LIMIT " ).append (count ).append ("\n " );
282+ query .append ("| STATS MAX(a)\n " );
283+ query .append ("\" }" );
284+ return query .toString ();
285+ }
286+
255287 /**
256288 * This groups on about 200 columns which is a lot but has never caused us trouble.
257289 */
258290 public void testGroupOnSomeLongs () throws IOException {
259- initManyLongs ();
291+ initManyLongs (10 );
260292 Response resp = groupOnManyLongs (200 );
261293 Map <String , Object > map = responseAsMap (resp );
262294 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -268,7 +300,7 @@ public void testGroupOnSomeLongs() throws IOException {
268300 * This groups on 5000 columns which used to throw a {@link StackOverflowError}.
269301 */
270302 public void testGroupOnManyLongs () throws IOException {
271- initManyLongs ();
303+ initManyLongs (10 );
272304 Response resp = groupOnManyLongs (5000 );
273305 Map <String , Object > map = responseAsMap (resp );
274306 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -336,15 +368,15 @@ private Response concat(int evals) throws IOException {
336368 */
337369 public void testManyConcat () throws IOException {
338370 int strings = 300 ;
339- initManyLongs ();
371+ initManyLongs (10 );
340372 assertManyStrings (manyConcat ("FROM manylongs" , strings ), strings );
341373 }
342374
343375 /**
344376 * Hits a circuit breaker by building many moderately long strings.
345377 */
346378 public void testHugeManyConcat () throws IOException {
347- initManyLongs ();
379+ initManyLongs (10 );
348380 // 2000 is plenty to break on most nodes
349381 assertCircuitBreaks (attempt -> manyConcat ("FROM manylongs" , attempt * 2000 ));
350382 }
@@ -415,15 +447,15 @@ private Map<String, Object> manyConcat(String init, int strings) throws IOExcept
415447 */
416448 public void testManyRepeat () throws IOException {
417449 int strings = 30 ;
418- initManyLongs ();
450+ initManyLongs (10 );
419451 assertManyStrings (manyRepeat ("FROM manylongs" , strings ), 30 );
420452 }
421453
422454 /**
423455 * Hits a circuit breaker by building many moderately long strings.
424456 */
425457 public void testHugeManyRepeat () throws IOException {
426- initManyLongs ();
458+ initManyLongs (10 );
427459 // 75 is plenty to break on most nodes
428460 assertCircuitBreaks (attempt -> manyRepeat ("FROM manylongs" , attempt * 75 ));
429461 }
@@ -481,7 +513,7 @@ private void assertManyStrings(Map<String, Object> resp, int strings) throws IOE
481513 }
482514
483515 public void testManyEval () throws IOException {
484- initManyLongs ();
516+ initManyLongs (10 );
485517 Map <String , Object > response = manyEval (1 );
486518 ListMatcher columns = matchesList ();
487519 columns = columns .item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ));
@@ -496,7 +528,7 @@ public void testManyEval() throws IOException {
496528 }
497529
498530 public void testTooManyEval () throws IOException {
499- initManyLongs ();
531+ initManyLongs (10 );
500532 // 490 is plenty to fail on most nodes
501533 assertCircuitBreaks (attempt -> manyEval (attempt * 490 ));
502534 }
@@ -855,24 +887,34 @@ private Map<String, Object> enrichExplosion(int sensorDataCount, int lookupEntri
855887 }
856888 }
857889
858- private void initManyLongs () throws IOException {
890+ private void initManyLongs (int countPerLong ) throws IOException {
859891 logger .info ("loading many documents with longs" );
860892 StringBuilder bulk = new StringBuilder ();
861- for (int a = 0 ; a < 10 ; a ++) {
862- for (int b = 0 ; b < 10 ; b ++) {
863- for (int c = 0 ; c < 10 ; c ++) {
864- for (int d = 0 ; d < 10 ; d ++) {
865- for (int e = 0 ; e < 10 ; e ++) {
893+ int flush = 0 ;
894+ for (int a = 0 ; a < countPerLong ; a ++) {
895+ for (int b = 0 ; b < countPerLong ; b ++) {
896+ for (int c = 0 ; c < countPerLong ; c ++) {
897+ for (int d = 0 ; d < countPerLong ; d ++) {
898+ for (int e = 0 ; e < countPerLong ; e ++) {
866899 bulk .append (String .format (Locale .ROOT , """
867900 {"create":{}}
868901 {"a":%d,"b":%d,"c":%d,"d":%d,"e":%d}
869902 """ , a , b , c , d , e ));
903+ flush ++;
904+ if (flush % 10_000 == 0 ) {
905+ bulk ("manylongs" , bulk .toString ());
906+ bulk .setLength (0 );
907+ logger .info (
908+ "flushing {}/{} to manylongs" ,
909+ flush ,
910+ countPerLong * countPerLong * countPerLong * countPerLong * countPerLong
911+ );
912+
913+ }
870914 }
871915 }
872916 }
873917 }
874- bulk ("manylongs" , bulk .toString ());
875- bulk .setLength (0 );
876918 }
877919 initIndex ("manylongs" , bulk .toString ());
878920 }
0 commit comments