modify QueryCapacityExceededException to provide better messaging (#9547)

* modify QueryCapacityExceededException to provide better messaging

* style
This commit is contained in:
Clint Wylie 2020-03-23 20:05:11 -07:00 committed by GitHub
parent bf85ea19b2
commit 2bc29543e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 32 additions and 25 deletions

View File

@ -21,7 +21,6 @@ package org.apache.druid.tests.query;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Inject; import com.google.inject.Inject;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.http.client.response.StatusResponseHolder; import org.apache.druid.java.util.http.client.response.StatusResponseHolder;
import org.apache.druid.query.Druids; import org.apache.druid.query.Druids;
import org.apache.druid.query.aggregation.CountAggregatorFactory; import org.apache.druid.query.aggregation.CountAggregatorFactory;
@ -110,7 +109,7 @@ public class ITWikipediaQueryTest
StatusResponseHolder status = future.get(); StatusResponseHolder status = future.get();
if (status.getStatus().getCode() == QueryCapacityExceededException.STATUS_CODE) { if (status.getStatus().getCode() == QueryCapacityExceededException.STATUS_CODE) {
limited++; limited++;
Assert.assertTrue(status.getContent().contains(StringUtils.format(QueryCapacityExceededException.ERROR_MESSAGE_TEMPLATE, "one"))); Assert.assertTrue(status.getContent().contains(QueryCapacityExceededException.makeLaneErrorMessage("one", 1)));
} else if (status.getStatus().getCode() == HttpResponseStatus.OK.getCode()) { } else if (status.getStatus().getCode() == HttpResponseStatus.OK.getCode()) {
success++; success++;
} }

View File

@ -21,6 +21,7 @@ package org.apache.druid.server;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.query.QueryException; import org.apache.druid.query.QueryException;
@ -33,20 +34,22 @@ import org.apache.druid.query.QueryException;
*/ */
public class QueryCapacityExceededException extends QueryException public class QueryCapacityExceededException extends QueryException
{ {
private static final String TOTAL_ERROR_MESSAGE_TEMPLATE =
"Too many concurrent queries, total query capacity of %s exceeded. Please try your query again later.";
private static final String LANE_ERROR_MESSAGE_TEMPLATE =
"Too many concurrent queries for lane '%s', query capacity of %s exceeded. Please try your query again later.";
private static final String ERROR_CLASS = QueryCapacityExceededException.class.getName(); private static final String ERROR_CLASS = QueryCapacityExceededException.class.getName();
public static final String ERROR_CODE = "Query capacity exceeded"; public static final String ERROR_CODE = "Query capacity exceeded";
public static final String ERROR_MESSAGE = "Total query capacity exceeded";
public static final String ERROR_MESSAGE_TEMPLATE = "Query capacity exceeded for lane '%s'";
public static final int STATUS_CODE = 429; public static final int STATUS_CODE = 429;
public QueryCapacityExceededException() public QueryCapacityExceededException(int capacity)
{ {
super(ERROR_CODE, ERROR_MESSAGE, ERROR_CLASS, null); super(ERROR_CODE, makeTotalErrorMessage(capacity), ERROR_CLASS, null);
} }
public QueryCapacityExceededException(String lane) public QueryCapacityExceededException(String lane, int capacity)
{ {
super(ERROR_CODE, StringUtils.format(ERROR_MESSAGE_TEMPLATE, lane), ERROR_CLASS, null); super(ERROR_CODE, makeLaneErrorMessage(lane, capacity), ERROR_CLASS, null);
} }
@JsonCreator @JsonCreator
@ -57,4 +60,16 @@ public class QueryCapacityExceededException extends QueryException
{ {
super(errorCode, errorMessage, errorClass, null); super(errorCode, errorMessage, errorClass, null);
} }
@VisibleForTesting
public static String makeTotalErrorMessage(int capacity)
{
return StringUtils.format(TOTAL_ERROR_MESSAGE_TEMPLATE, capacity);
}
@VisibleForTesting
public static String makeLaneErrorMessage(String lane, int capacity)
{
return StringUtils.format(LANE_ERROR_MESSAGE_TEMPLATE, lane, capacity);
}
} }

View File

@ -202,7 +202,7 @@ public class QueryScheduler implements QueryWatcher
laneConfig.ifPresent(config -> { laneConfig.ifPresent(config -> {
Bulkhead laneLimiter = laneRegistry.bulkhead(lane, config); Bulkhead laneLimiter = laneRegistry.bulkhead(lane, config);
if (!laneLimiter.tryAcquirePermission()) { if (!laneLimiter.tryAcquirePermission()) {
throw new QueryCapacityExceededException(lane); throw new QueryCapacityExceededException(lane, config.getMaxConcurrentCalls());
} }
hallPasses.add(laneLimiter); hallPasses.add(laneLimiter);
}); });
@ -214,7 +214,7 @@ public class QueryScheduler implements QueryWatcher
totalConfig.ifPresent(config -> { totalConfig.ifPresent(config -> {
Bulkhead totalLimiter = laneRegistry.bulkhead(TOTAL, config); Bulkhead totalLimiter = laneRegistry.bulkhead(TOTAL, config);
if (!totalLimiter.tryAcquirePermission()) { if (!totalLimiter.tryAcquirePermission()) {
throw new QueryCapacityExceededException(); throw new QueryCapacityExceededException(config.getMaxConcurrentCalls());
} }
hallPasses.add(totalLimiter); hallPasses.add(totalLimiter);
}); });

View File

@ -28,7 +28,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
import org.apache.druid.jackson.DefaultObjectMapper; import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.concurrent.Execs; import org.apache.druid.java.util.common.concurrent.Execs;
import org.apache.druid.java.util.common.guava.LazySequence; import org.apache.druid.java.util.common.guava.LazySequence;
import org.apache.druid.java.util.common.guava.Sequences; import org.apache.druid.java.util.common.guava.Sequences;
@ -86,7 +85,8 @@ public class QueryResourceTest
{ {
private static final QueryToolChestWarehouse WAREHOUSE = new MapQueryToolChestWarehouse(ImmutableMap.of()); private static final QueryToolChestWarehouse WAREHOUSE = new MapQueryToolChestWarehouse(ImmutableMap.of());
private static final ObjectMapper JSON_MAPPER = new DefaultObjectMapper(); private static final ObjectMapper JSON_MAPPER = new DefaultObjectMapper();
private static final AuthenticationResult AUTHENTICATION_RESULT = new AuthenticationResult("druid", "druid", null, null); private static final AuthenticationResult AUTHENTICATION_RESULT =
new AuthenticationResult("druid", "druid", null, null);
private final HttpServletRequest testServletRequest = EasyMock.createMock(HttpServletRequest.class); private final HttpServletRequest testServletRequest = EasyMock.createMock(HttpServletRequest.class);
@ -728,7 +728,7 @@ public class QueryResourceTest
catch (IOException e) { catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
Assert.assertEquals(QueryCapacityExceededException.ERROR_MESSAGE, ex.getMessage()); Assert.assertEquals(QueryCapacityExceededException.makeTotalErrorMessage(2), ex.getMessage());
Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode()); Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode());
} }
); );
@ -770,10 +770,7 @@ public class QueryResourceTest
throw new RuntimeException(e); throw new RuntimeException(e);
} }
Assert.assertEquals( Assert.assertEquals(
StringUtils.format( QueryCapacityExceededException.makeLaneErrorMessage(HiLoQueryLaningStrategy.LOW, 1),
QueryCapacityExceededException.ERROR_MESSAGE_TEMPLATE,
HiLoQueryLaningStrategy.LOW
),
ex.getMessage() ex.getMessage()
); );
Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode()); Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode());
@ -825,10 +822,7 @@ public class QueryResourceTest
throw new RuntimeException(e); throw new RuntimeException(e);
} }
Assert.assertEquals( Assert.assertEquals(
StringUtils.format( QueryCapacityExceededException.makeLaneErrorMessage(HiLoQueryLaningStrategy.LOW, 1),
QueryCapacityExceededException.ERROR_MESSAGE_TEMPLATE,
HiLoQueryLaningStrategy.LOW
),
ex.getMessage() ex.getMessage()
); );
Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode()); Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, ex.getErrorCode());

View File

@ -37,7 +37,6 @@ import org.apache.druid.guice.JsonConfigProvider;
import org.apache.druid.guice.JsonConfigurator; import org.apache.druid.guice.JsonConfigurator;
import org.apache.druid.guice.annotations.Global; import org.apache.druid.guice.annotations.Global;
import org.apache.druid.guice.annotations.Json; import org.apache.druid.guice.annotations.Json;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.java.util.common.concurrent.Execs; import org.apache.druid.java.util.common.concurrent.Execs;
import org.apache.druid.java.util.common.guava.BaseSequence; import org.apache.druid.java.util.common.guava.BaseSequence;
import org.apache.druid.java.util.common.guava.LazySequence; import org.apache.druid.java.util.common.guava.LazySequence;
@ -212,7 +211,7 @@ public class QuerySchedulerTest
public void testHiLoFailsWhenOutOfLaneCapacity() public void testHiLoFailsWhenOutOfLaneCapacity()
{ {
expected.expectMessage( expected.expectMessage(
StringUtils.format(QueryCapacityExceededException.ERROR_MESSAGE_TEMPLATE, HiLoQueryLaningStrategy.LOW) QueryCapacityExceededException.makeLaneErrorMessage(HiLoQueryLaningStrategy.LOW, TEST_LO_CAPACITY)
); );
expected.expect(QueryCapacityExceededException.class); expected.expect(QueryCapacityExceededException.class);
@ -237,7 +236,7 @@ public class QuerySchedulerTest
@Test @Test
public void testHiLoFailsWhenOutOfTotalCapacity() public void testHiLoFailsWhenOutOfTotalCapacity()
{ {
expected.expectMessage(QueryCapacityExceededException.ERROR_MESSAGE); expected.expectMessage(QueryCapacityExceededException.makeTotalErrorMessage(TEST_HI_CAPACITY));
expected.expect(QueryCapacityExceededException.class); expected.expect(QueryCapacityExceededException.class);
Query<?> interactive1 = scheduler.prioritizeAndLaneQuery(QueryPlus.wrap(makeInteractiveQuery()), ImmutableSet.of()); Query<?> interactive1 = scheduler.prioritizeAndLaneQuery(QueryPlus.wrap(makeInteractiveQuery()), ImmutableSet.of());

View File

@ -756,7 +756,7 @@ public class SqlResourceTest extends CalciteTestBase
QueryException interruped = result.lhs; QueryException interruped = result.lhs;
Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, interruped.getErrorCode()); Assert.assertEquals(QueryCapacityExceededException.ERROR_CODE, interruped.getErrorCode());
Assert.assertEquals( Assert.assertEquals(
StringUtils.format(QueryCapacityExceededException.ERROR_MESSAGE_TEMPLATE, HiLoQueryLaningStrategy.LOW), QueryCapacityExceededException.makeLaneErrorMessage(HiLoQueryLaningStrategy.LOW, 2),
interruped.getMessage() interruped.getMessage()
); );
limited++; limited++;