@@ -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,29 @@ 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+ .entry ("documents_found" , greaterThan (0 ))
203+ .entry ("values_loaded" , greaterThan (0 ))
204+ );
205+ }
206+
207+ public void testSortByManyLongsGiantTopNTooMuchMemory () throws IOException {
208+ initManyLongs (20 );
209+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (attempt * 500000 ));
210+ }
211+
212+ public void testStupidTopN () throws IOException {
213+ initManyLongs (1 ); // Doesn't actually matter how much data there is.
214+ assertCircuitBreaks (attempt -> sortBySomeLongsLimit (2147483630 ));
215+ }
216+
194217 private static final int MAX_ATTEMPTS = 5 ;
195218
196219 interface TryCircuitBreaking {
@@ -249,11 +272,25 @@ private StringBuilder makeSortByManyLongs(int count) {
249272 return query ;
250273 }
251274
275+ private Map <String , Object > sortBySomeLongsLimit (int count ) throws IOException {
276+ logger .info ("sorting by 5 longs, keeping {}" , count );
277+ return responseAsMap (query (makeSortBySomeLongsLimit (count ), null ));
278+ }
279+
280+ private String makeSortBySomeLongsLimit (int count ) {
281+ StringBuilder query = new StringBuilder ("{\" query\" : \" FROM manylongs\n " );
282+ query .append ("| SORT a, b, c, d, e\n " );
283+ query .append ("| LIMIT " ).append (count ).append ("\n " );
284+ query .append ("| STATS MAX(a)\n " );
285+ query .append ("\" }" );
286+ return query .toString ();
287+ }
288+
252289 /**
253290 * This groups on about 200 columns which is a lot but has never caused us trouble.
254291 */
255292 public void testGroupOnSomeLongs () throws IOException {
256- initManyLongs ();
293+ initManyLongs (10 );
257294 Response resp = groupOnManyLongs (200 );
258295 Map <String , Object > map = responseAsMap (resp );
259296 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -265,7 +302,7 @@ public void testGroupOnSomeLongs() throws IOException {
265302 * This groups on 5000 columns which used to throw a {@link StackOverflowError}.
266303 */
267304 public void testGroupOnManyLongs () throws IOException {
268- initManyLongs ();
305+ initManyLongs (10 );
269306 Response resp = groupOnManyLongs (5000 );
270307 Map <String , Object > map = responseAsMap (resp );
271308 ListMatcher columns = matchesList ().item (matchesMap ().entry ("name" , "MAX(a)" ).entry ("type" , "long" ));
@@ -333,15 +370,15 @@ private Response concat(int evals) throws IOException {
333370 */
334371 public void testManyConcat () throws IOException {
335372 int strings = 300 ;
336- initManyLongs ();
373+ initManyLongs (10 );
337374 assertManyStrings (manyConcat ("FROM manylongs" , strings ), strings );
338375 }
339376
340377 /**
341378 * Hits a circuit breaker by building many moderately long strings.
342379 */
343380 public void testHugeManyConcat () throws IOException {
344- initManyLongs ();
381+ initManyLongs (10 );
345382 // 2000 is plenty to break on most nodes
346383 assertCircuitBreaks (attempt -> manyConcat ("FROM manylongs" , attempt * 2000 ));
347384 }
@@ -412,15 +449,15 @@ private Map<String, Object> manyConcat(String init, int strings) throws IOExcept
412449 */
413450 public void testManyRepeat () throws IOException {
414451 int strings = 30 ;
415- initManyLongs ();
452+ initManyLongs (10 );
416453 assertManyStrings (manyRepeat ("FROM manylongs" , strings ), 30 );
417454 }
418455
419456 /**
420457 * Hits a circuit breaker by building many moderately long strings.
421458 */
422459 public void testHugeManyRepeat () throws IOException {
423- initManyLongs ();
460+ initManyLongs (10 );
424461 // 75 is plenty to break on most nodes
425462 assertCircuitBreaks (attempt -> manyRepeat ("FROM manylongs" , attempt * 75 ));
426463 }
@@ -478,7 +515,7 @@ private void assertManyStrings(Map<String, Object> resp, int strings) throws IOE
478515 }
479516
480517 public void testManyEval () throws IOException {
481- initManyLongs ();
518+ initManyLongs (10 );
482519 Map <String , Object > response = manyEval (1 );
483520 ListMatcher columns = matchesList ();
484521 columns = columns .item (matchesMap ().entry ("name" , "a" ).entry ("type" , "long" ));
@@ -493,7 +530,7 @@ public void testManyEval() throws IOException {
493530 }
494531
495532 public void testTooManyEval () throws IOException {
496- initManyLongs ();
533+ initManyLongs (10 );
497534 // 490 is plenty to fail on most nodes
498535 assertCircuitBreaks (attempt -> manyEval (attempt * 490 ));
499536 }
@@ -808,24 +845,34 @@ private Map<String, Object> enrichExplosion(int sensorDataCount, int lookupEntri
808845 }
809846 }
810847
811- private void initManyLongs () throws IOException {
848+ private void initManyLongs (int countPerLong ) throws IOException {
812849 logger .info ("loading many documents with longs" );
813850 StringBuilder bulk = new StringBuilder ();
814- for (int a = 0 ; a < 10 ; a ++) {
815- for (int b = 0 ; b < 10 ; b ++) {
816- for (int c = 0 ; c < 10 ; c ++) {
817- for (int d = 0 ; d < 10 ; d ++) {
818- for (int e = 0 ; e < 10 ; e ++) {
851+ int flush = 0 ;
852+ for (int a = 0 ; a < countPerLong ; a ++) {
853+ for (int b = 0 ; b < countPerLong ; b ++) {
854+ for (int c = 0 ; c < countPerLong ; c ++) {
855+ for (int d = 0 ; d < countPerLong ; d ++) {
856+ for (int e = 0 ; e < countPerLong ; e ++) {
819857 bulk .append (String .format (Locale .ROOT , """
820858 {"create":{}}
821859 {"a":%d,"b":%d,"c":%d,"d":%d,"e":%d}
822860 """ , a , b , c , d , e ));
861+ flush ++;
862+ if (flush % 10_000 == 0 ) {
863+ bulk ("manylongs" , bulk .toString ());
864+ bulk .setLength (0 );
865+ logger .info (
866+ "flushing {}/{} to manylongs" ,
867+ flush ,
868+ countPerLong * countPerLong * countPerLong * countPerLong * countPerLong
869+ );
870+
871+ }
823872 }
824873 }
825874 }
826875 }
827- bulk ("manylongs" , bulk .toString ());
828- bulk .setLength (0 );
829876 }
830877 initIndex ("manylongs" , bulk .toString ());
831878 }
0 commit comments