@@ -88,7 +88,7 @@ public void skipOnAborted() {
8888 * This used to fail, but we've since compacted top n so it actually succeeds now.
8989 */
9090 public void testSortByManyLongsSuccess () throws IOException {
91- initManyLongs ();
91+ initManyLongs (10 );
9292 Map <String , Object > response = sortByManyLongs (500 );
9393 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ))
9494 .item (matchesMap ().entry ("name" , "b" ).entry ("type" , "long" ));
@@ -105,7 +105,7 @@ public void testSortByManyLongsSuccess() throws IOException {
105105 * This used to crash the node with an out of memory, but now it just trips a circuit breaker.
106106 */
107107 public void testSortByManyLongsTooMuchMemory () throws IOException {
108- initManyLongs ();
108+ initManyLongs (10 );
109109 // 5000 is plenty to break on most nodes
110110 assertCircuitBreaks (attempt -> sortByManyLongs (attempt * 5000 ));
111111 }
@@ -114,7 +114,7 @@ public void testSortByManyLongsTooMuchMemory() throws IOException {
114114 * This should record an async response with a {@link CircuitBreakingException}.
115115 */
116116 public void testSortByManyLongsTooMuchMemoryAsync () throws IOException {
117- initManyLongs ();
117+ initManyLongs (10 );
118118 Request request = new Request ("POST" , "/_query/async" );
119119 request .addParameter ("error_trace" , "" );
120120 request .setJsonEntity (makeSortByManyLongs (5000 ).toString ().replace ("\n " , "\\ n" ));
@@ -191,6 +191,22 @@ public void testSortByManyLongsTooMuchMemoryAsync() throws IOException {
191191 );
192192 }
193193
194+ public void testSortByManyLongsGiantTopN () throws IOException {
195+ initManyLongs (10 );
196+ assertMap (
197+ sortBySomeLongsLimit (100000 ),
198+ matchesMap ().entry ("took" , greaterThan (0 ))
199+ .entry ("is_partial" , false )
200+ .entry ("columns" , List .of (Map .of ("name" , "MAX(a)" , "type" , "long" )))
201+ .entry ("values" , List .of (List .of (9 )))
202+ );
203+ }
204+
205+ public void testStupidTopN () throws IOException {
206+ initManyLongs (1 ); // Doesn't actually matter how much data there is.
207+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (2147483630 ));
208+ }
209+
194210 private static final int MAX_ATTEMPTS = 5 ;
195211
196212 interface TryCircuitBreaking {
@@ -249,11 +265,25 @@ private StringBuilder makeSortByManyLongs(int count) {
249265 return query ;
250266 }
251267
268+ private Map <String , Object > sortBySomeLongsLimit (int count ) throws IOException {
269+ logger .info ("sorting by 5 longs, keeping {}" , count );
270+ return responseAsMap (query (makeSortBySomeLongsLimit (count ), null ));
271+ }
272+
273+ private String makeSortBySomeLongsLimit (int count ) {
274+ StringBuilder query = new StringBuilder ("{\" query\" : \" FROM manylongs\n " );
275+ query .append ("| SORT a, b, c, d, e\n " );
276+ query .append ("| LIMIT " ).append (count ).append ("\n " );
277+ query .append ("| STATS MAX(a)\n " );
278+ query .append ("\" }" );
279+ return query .toString ();
280+ }
281+
252282 /**
253283 * This groups on about 200 columns which is a lot but has never caused us trouble.
254284 */
255285 public void testGroupOnSomeLongs () throws IOException {
256- initManyLongs ();
286+ initManyLongs (10 );
257287 Response resp = groupOnManyLongs (200 );
258288 Map <String , Object > map = responseAsMap (resp );
259289 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -265,7 +295,7 @@ public void testGroupOnSomeLongs() throws IOException {
265295 * This groups on 5000 columns which used to throw a {@link StackOverflowError}.
266296 */
267297 public void testGroupOnManyLongs () throws IOException {
268- initManyLongs ();
298+ initManyLongs (10 );
269299 Response resp = groupOnManyLongs (5000 );
270300 Map <String , Object > map = responseAsMap (resp );
271301 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -333,15 +363,15 @@ private Response concat(int evals) throws IOException {
333363 */
334364 public void testManyConcat () throws IOException {
335365 int strings = 300 ;
336- initManyLongs ();
366+ initManyLongs (10 );
337367 assertManyStrings (manyConcat ("FROM manylongs" , strings ), strings );
338368 }
339369
340370 /**
341371 * Hits a circuit breaker by building many moderately long strings.
342372 */
343373 public void testHugeManyConcat () throws IOException {
344- initManyLongs ();
374+ initManyLongs (10 );
345375 // 2000 is plenty to break on most nodes
346376 assertCircuitBreaks (attempt -> manyConcat ("FROM manylongs" , attempt * 2000 ));
347377 }
@@ -412,15 +442,15 @@ private Map<String, Object> manyConcat(String init, int strings) throws IOExcept
412442 */
413443 public void testManyRepeat () throws IOException {
414444 int strings = 30 ;
415- initManyLongs ();
445+ initManyLongs (10 );
416446 assertManyStrings (manyRepeat ("FROM manylongs" , strings ), 30 );
417447 }
418448
419449 /**
420450 * Hits a circuit breaker by building many moderately long strings.
421451 */
422452 public void testHugeManyRepeat () throws IOException {
423- initManyLongs ();
453+ initManyLongs (10 );
424454 // 75 is plenty to break on most nodes
425455 assertCircuitBreaks (attempt -> manyRepeat ("FROM manylongs" , attempt * 75 ));
426456 }
@@ -478,7 +508,7 @@ private void assertManyStrings(Map<String, Object> resp, int strings) throws IOE
478508 }
479509
480510 public void testManyEval () throws IOException {
481- initManyLongs ();
511+ initManyLongs (10 );
482512 Map <String , Object > response = manyEval (1 );
483513 ListMatcher columns = matchesList ();
484514 columns = columns .item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ));
@@ -493,7 +523,7 @@ public void testManyEval() throws IOException {
493523 }
494524
495525 public void testTooManyEval () throws IOException {
496- initManyLongs ();
526+ initManyLongs (10 );
497527 // 490 is plenty to fail on most nodes
498528 assertCircuitBreaks (attempt -> manyEval (attempt * 490 ));
499529 }
@@ -756,24 +786,34 @@ private Map<String, Object> enrichExplosion(int sensorDataCount, int lookupEntri
756786 }
757787 }
758788
759- private void initManyLongs () throws IOException {
789+ private void initManyLongs (int countPerLong ) throws IOException {
760790 logger .info ("loading many documents with longs" );
761791 StringBuilder bulk = new StringBuilder ();
762- for (int a = 0 ; a < 10 ; a ++) {
763- for (int b = 0 ; b < 10 ; b ++) {
764- for (int c = 0 ; c < 10 ; c ++) {
765- for (int d = 0 ; d < 10 ; d ++) {
766- for (int e = 0 ; e < 10 ; e ++) {
792+ int flush = 0 ;
793+ for (int a = 0 ; a < countPerLong ; a ++) {
794+ for (int b = 0 ; b < countPerLong ; b ++) {
795+ for (int c = 0 ; c < countPerLong ; c ++) {
796+ for (int d = 0 ; d < countPerLong ; d ++) {
797+ for (int e = 0 ; e < countPerLong ; e ++) {
767798 bulk .append (String .format (Locale .ROOT , """
768799 {"create":{}}
769800 {"a":%d,"b":%d,"c":%d,"d":%d,"e":%d}
770801 """ , a , b , c , d , e ));
802+ flush ++;
803+ if (flush % 10_000 == 0 ) {
804+ bulk ("manylongs" , bulk .toString ());
805+ bulk .setLength (0 );
806+ logger .info (
807+ "flushing {}/{} to manylongs" ,
808+ flush ,
809+ countPerLong * countPerLong * countPerLong * countPerLong * countPerLong
810+ );
811+
812+ }
771813 }
772814 }
773815 }
774816 }
775- bulk ("manylongs" , bulk .toString ());
776- bulk .setLength (0 );
777817 }
778818 initIndex ("manylongs" , bulk .toString ());
779819 }
0 commit comments