mirror of
https://github.com/apache/druid.git
synced 2025-02-20 00:47:40 +00:00
Introduce standardized "Resource limit exceeded" error. (#3338)
Fixes #3336.
This commit is contained in:
parent
21bce96c4c
commit
8899affe48
@ -97,4 +97,5 @@ Possible codes for the *error* field include:
|
|||||||
|`Query timeout`|The query timed out.|
|
|`Query timeout`|The query timed out.|
|
||||||
|`Query interrupted`|The query was interrupted, possibly due to JVM shutdown.|
|
|`Query interrupted`|The query was interrupted, possibly due to JVM shutdown.|
|
||||||
|`Query cancelled`|The query was cancelled through the query cancellation API.|
|
|`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.|
|
|`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.|
|
||||||
|
@ -44,6 +44,7 @@ public class QueryInterruptedException extends RuntimeException
|
|||||||
public static final String QUERY_INTERRUPTED = "Query interrupted";
|
public static final String QUERY_INTERRUPTED = "Query interrupted";
|
||||||
public static final String QUERY_TIMEOUT = "Query timeout";
|
public static final String QUERY_TIMEOUT = "Query timeout";
|
||||||
public static final String QUERY_CANCELLED = "Query cancelled";
|
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";
|
public static final String UNKNOWN_EXCEPTION = "Unknown exception";
|
||||||
|
|
||||||
private final String errorCode;
|
private final String errorCode;
|
||||||
@ -118,6 +119,8 @@ public class QueryInterruptedException extends RuntimeException
|
|||||||
return QUERY_CANCELLED;
|
return QUERY_CANCELLED;
|
||||||
} else if (e instanceof TimeoutException) {
|
} else if (e instanceof TimeoutException) {
|
||||||
return QUERY_TIMEOUT;
|
return QUERY_TIMEOUT;
|
||||||
|
} else if (e instanceof ResourceLimitExceededException) {
|
||||||
|
return RESOURCE_LIMIT_EXCEEDED;
|
||||||
} else {
|
} else {
|
||||||
return UNKNOWN_EXCEPTION;
|
return UNKNOWN_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ import io.druid.data.input.MapBasedInputRow;
|
|||||||
import io.druid.data.input.MapBasedRow;
|
import io.druid.data.input.MapBasedRow;
|
||||||
import io.druid.data.input.Row;
|
import io.druid.data.input.Row;
|
||||||
import io.druid.granularity.QueryGranularity;
|
import io.druid.granularity.QueryGranularity;
|
||||||
|
import io.druid.query.ResourceLimitExceededException;
|
||||||
import io.druid.query.aggregation.AggregatorFactory;
|
import io.druid.query.aggregation.AggregatorFactory;
|
||||||
import io.druid.query.dimension.DimensionSpec;
|
import io.druid.query.dimension.DimensionSpec;
|
||||||
import io.druid.segment.incremental.IncrementalIndex;
|
import io.druid.segment.incremental.IncrementalIndex;
|
||||||
@ -132,7 +133,7 @@ public class GroupByQueryHelper
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
catch (IndexSizeExceededException e) {
|
catch (IndexSizeExceededException e) {
|
||||||
throw new ISE(e.getMessage());
|
throw new ResourceLimitExceededException(e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new ISE("Unable to accumulate something of type [%s]", in.getClass());
|
throw new ISE("Unable to accumulate something of type [%s]", in.getClass());
|
||||||
|
@ -50,6 +50,7 @@ import io.druid.query.QueryContextKeys;
|
|||||||
import io.druid.query.QueryInterruptedException;
|
import io.druid.query.QueryInterruptedException;
|
||||||
import io.druid.query.QueryRunner;
|
import io.druid.query.QueryRunner;
|
||||||
import io.druid.query.QueryWatcher;
|
import io.druid.query.QueryWatcher;
|
||||||
|
import io.druid.query.ResourceLimitExceededException;
|
||||||
import io.druid.query.aggregation.AggregatorFactory;
|
import io.druid.query.aggregation.AggregatorFactory;
|
||||||
import io.druid.query.groupby.GroupByQuery;
|
import io.druid.query.groupby.GroupByQuery;
|
||||||
import io.druid.query.groupby.GroupByQueryConfig;
|
import io.druid.query.groupby.GroupByQueryConfig;
|
||||||
@ -308,7 +309,7 @@ public class GroupByMergingQueryRunnerV2 implements QueryRunner
|
|||||||
for (Boolean result : results) {
|
for (Boolean result : results) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
throw new ISE("Grouping resources exhausted");
|
throw new ResourceLimitExceededException("Grouping resources exhausted");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,10 @@ public class QueryInterruptedExceptionTest
|
|||||||
Assert.assertEquals("Query timeout", new QueryInterruptedException(new TimeoutException()).getErrorCode());
|
Assert.assertEquals("Query timeout", new QueryInterruptedException(new TimeoutException()).getErrorCode());
|
||||||
Assert.assertEquals("Unknown exception", new QueryInterruptedException(null).getErrorCode());
|
Assert.assertEquals("Unknown exception", new QueryInterruptedException(null).getErrorCode());
|
||||||
Assert.assertEquals("Unknown exception", new QueryInterruptedException(new ISE("Something bad!")).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(
|
Assert.assertEquals(
|
||||||
"Unknown exception",
|
"Unknown exception",
|
||||||
new QueryInterruptedException(new QueryInterruptedException(new ISE("Something bad!"))).getErrorCode()
|
new QueryInterruptedException(new QueryInterruptedException(new ISE("Something bad!"))).getErrorCode()
|
||||||
@ -74,6 +78,10 @@ public class QueryInterruptedExceptionTest
|
|||||||
null,
|
null,
|
||||||
new QueryInterruptedException(null).getMessage()
|
new QueryInterruptedException(null).getMessage()
|
||||||
);
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"too many!",
|
||||||
|
new QueryInterruptedException(new ResourceLimitExceededException("too many!")).getMessage()
|
||||||
|
);
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
"Something bad!",
|
"Something bad!",
|
||||||
new QueryInterruptedException(new ISE("Something bad!")).getMessage()
|
new QueryInterruptedException(new ISE("Something bad!")).getMessage()
|
||||||
@ -103,6 +111,10 @@ public class QueryInterruptedExceptionTest
|
|||||||
"java.util.concurrent.TimeoutException",
|
"java.util.concurrent.TimeoutException",
|
||||||
new QueryInterruptedException(new TimeoutException()).getErrorClass()
|
new QueryInterruptedException(new TimeoutException()).getErrorClass()
|
||||||
);
|
);
|
||||||
|
Assert.assertEquals(
|
||||||
|
"io.druid.query.ResourceLimitExceededException",
|
||||||
|
new QueryInterruptedException(new ResourceLimitExceededException("too many!")).getErrorClass()
|
||||||
|
);
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
null,
|
null,
|
||||||
new QueryInterruptedException(null).getErrorClass()
|
new QueryInterruptedException(null).getErrorClass()
|
||||||
|
@ -50,6 +50,7 @@ import io.druid.query.Query;
|
|||||||
import io.druid.query.QueryRunner;
|
import io.druid.query.QueryRunner;
|
||||||
import io.druid.query.QueryRunnerTestHelper;
|
import io.druid.query.QueryRunnerTestHelper;
|
||||||
import io.druid.query.QueryToolChest;
|
import io.druid.query.QueryToolChest;
|
||||||
|
import io.druid.query.ResourceLimitExceededException;
|
||||||
import io.druid.query.Result;
|
import io.druid.query.Result;
|
||||||
import io.druid.query.aggregation.AggregatorFactory;
|
import io.druid.query.aggregation.AggregatorFactory;
|
||||||
import io.druid.query.aggregation.CountAggregatorFactory;
|
import io.druid.query.aggregation.CountAggregatorFactory;
|
||||||
@ -875,7 +876,7 @@ public class GroupByQueryRunnerTest
|
|||||||
|
|
||||||
List<Row> expectedResults = null;
|
List<Row> expectedResults = null;
|
||||||
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V1)) {
|
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V1)) {
|
||||||
expectedException.expect(ISE.class);
|
expectedException.expect(ResourceLimitExceededException.class);
|
||||||
} else {
|
} else {
|
||||||
expectedResults = Arrays.asList(
|
expectedResults = Arrays.asList(
|
||||||
GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "automotive", "rows", 1L, "idx", 135L),
|
GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "automotive", "rows", 1L, "idx", 135L),
|
||||||
@ -968,7 +969,7 @@ public class GroupByQueryRunnerTest
|
|||||||
|
|
||||||
List<Row> expectedResults = null;
|
List<Row> expectedResults = null;
|
||||||
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V2)) {
|
if (config.getDefaultStrategy().equals(GroupByStrategySelector.STRATEGY_V2)) {
|
||||||
expectedException.expect(ISE.class);
|
expectedException.expect(ResourceLimitExceededException.class);
|
||||||
expectedException.expectMessage("Grouping resources exhausted");
|
expectedException.expectMessage("Grouping resources exhausted");
|
||||||
} else {
|
} else {
|
||||||
expectedResults = Arrays.asList(
|
expectedResults = Arrays.asList(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user