Introduce standardized "Resource limit exceeded" error. (#3338)

Fixes #3336.
This commit is contained in:
Gian Merlino 2016-08-09 10:50:56 -07:00 committed by GitHub
parent 21bce96c4c
commit 8899affe48
7 changed files with 57 additions and 4 deletions

View File

@ -97,4 +97,5 @@ Possible codes for the *error* field include:
|`Query timeout`|The query timed out.|
|`Query interrupted`|The query was interrupted, possibly due to JVM shutdown.|
|`Query cancelled`|The query was cancelled through the query cancellation API.|
|`Resource limit exceeded`|The query exceeded a configured resource limit (e.g. groupBy maxResults).|
|`Unknown exception`|Some other exception occurred. Check errorMessage and errorClass for details, although keep in mind that the contents of those fields are free-form and may change from release to release.|

View File

@ -44,6 +44,7 @@ public class QueryInterruptedException extends RuntimeException
public static final String QUERY_INTERRUPTED = "Query interrupted";
public static final String QUERY_TIMEOUT = "Query timeout";
public static final String QUERY_CANCELLED = "Query cancelled";
public static final String RESOURCE_LIMIT_EXCEEDED = "Resource limit exceeded";
public static final String UNKNOWN_EXCEPTION = "Unknown exception";
private final String errorCode;
@ -118,6 +119,8 @@ public class QueryInterruptedException extends RuntimeException
return QUERY_CANCELLED;
} else if (e instanceof TimeoutException) {
return QUERY_TIMEOUT;
} else if (e instanceof ResourceLimitExceededException) {
return RESOURCE_LIMIT_EXCEEDED;
} else {
return UNKNOWN_EXCEPTION;
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.druid.query;
/**
* Exception indicating that an operation failed because it exceeded some configured resource limit.
*
* This is used as a marker exception by {@link QueryInterruptedException} to report the "Resource limit exceeded"
* error code.
*/
public class ResourceLimitExceededException extends RuntimeException
{
public ResourceLimitExceededException(String message)
{
super(message);
}
}

View File

@ -31,6 +31,7 @@ import io.druid.data.input.MapBasedInputRow;
import io.druid.data.input.MapBasedRow;
import io.druid.data.input.Row;
import io.druid.granularity.QueryGranularity;
import io.druid.query.ResourceLimitExceededException;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.dimension.DimensionSpec;
import io.druid.segment.incremental.IncrementalIndex;
@ -132,7 +133,7 @@ public class GroupByQueryHelper
);
}
catch (IndexSizeExceededException e) {
throw new ISE(e.getMessage());
throw new ResourceLimitExceededException(e.getMessage());
}
} else {
throw new ISE("Unable to accumulate something of type [%s]", in.getClass());

View File

@ -50,6 +50,7 @@ import io.druid.query.QueryContextKeys;
import io.druid.query.QueryInterruptedException;
import io.druid.query.QueryRunner;
import io.druid.query.QueryWatcher;
import io.druid.query.ResourceLimitExceededException;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.groupby.GroupByQuery;
import io.druid.query.groupby.GroupByQueryConfig;
@ -308,7 +309,7 @@ public class GroupByMergingQueryRunnerV2 implements QueryRunner
for (Boolean result : results) {
if (!result) {
future.cancel(true);
throw new ISE("Grouping resources exhausted");
throw new ResourceLimitExceededException("Grouping resources exhausted");
}
}
}

View File

@ -45,6 +45,10 @@ public class QueryInterruptedExceptionTest
Assert.assertEquals("Query timeout", new QueryInterruptedException(new TimeoutException()).getErrorCode());
Assert.assertEquals("Unknown exception", new QueryInterruptedException(null).getErrorCode());
Assert.assertEquals("Unknown exception", new QueryInterruptedException(new ISE("Something bad!")).getErrorCode());
Assert.assertEquals(
"Resource limit exceeded",
new QueryInterruptedException(new ResourceLimitExceededException("too many!")).getErrorCode()
);
Assert.assertEquals(
"Unknown exception",
new QueryInterruptedException(new QueryInterruptedException(new ISE("Something bad!"))).getErrorCode()
@ -74,6 +78,10 @@ public class QueryInterruptedExceptionTest
null,
new QueryInterruptedException(null).getMessage()
);
Assert.assertEquals(
"too many!",
new QueryInterruptedException(new ResourceLimitExceededException("too many!")).getMessage()
);
Assert.assertEquals(
"Something bad!",
new QueryInterruptedException(new ISE("Something bad!")).getMessage()
@ -103,6 +111,10 @@ public class QueryInterruptedExceptionTest
"java.util.concurrent.TimeoutException",
new QueryInterruptedException(new TimeoutException()).getErrorClass()
);
Assert.assertEquals(
"io.druid.query.ResourceLimitExceededException",
new QueryInterruptedException(new ResourceLimitExceededException("too many!")).getErrorClass()
);
Assert.assertEquals(
null,
new QueryInterruptedException(null).getErrorClass()

View File

@ -50,6 +50,7 @@ import io.druid.query.Query;
import io.druid.query.QueryRunner;
import io.druid.query.QueryRunnerTestHelper;
import io.druid.query.QueryToolChest;
import io.druid.query.ResourceLimitExceededException;
import io.druid.query.Result;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.aggregation.CountAggregatorFactory;
@ -875,7 +876,7 @@ public class GroupByQueryRunnerTest
List<Row> expectedResults = null;
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V1)) {
expectedException.expect(ISE.class);
expectedException.expect(ResourceLimitExceededException.class);
} else {
expectedResults = Arrays.asList(
GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "automotive", "rows", 1L, "idx", 135L),
@ -968,7 +969,7 @@ public class GroupByQueryRunnerTest
List<Row> expectedResults = null;
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V2)) {
expectedException.expect(ISE.class);
expectedException.expect(ResourceLimitExceededException.class);
expectedException.expectMessage("Grouping resources exhausted");
} else {
expectedResults = Arrays.asList(