diff --git a/presto-docs/src/main/sphinx/admin/properties-session.rst b/presto-docs/src/main/sphinx/admin/properties-session.rst index 9e2df6e92089..6cd5f9c3ccbf 100644 --- a/presto-docs/src/main/sphinx/admin/properties-session.rst +++ b/presto-docs/src/main/sphinx/admin/properties-session.rst @@ -484,4 +484,14 @@ The corresponding configuration property is :ref:`admin/properties:\`\`query.cli * **Default value:** ``1`` This property defines the priority of queries for execution and plays an important role in query admission. -Queries with higher priority are scheduled first than the ones with lower priority. Higher number indicates higher priority. \ No newline at end of file +Queries with higher priority are scheduled first than the ones with lower priority. Higher number indicates higher priority. + +``query_max_queued_time`` +^^^^^^^^^^^^^^^^^^^^^^^^^ + +* **Type:** ``Duration`` +* **Default value:** ``100d`` + +Use to configure how long a query can be queued before it is terminated. + +The corresponding configuration property is :ref:`admin/properties:\`\`query.max-queued-time\`\``. \ No newline at end of file diff --git a/presto-docs/src/main/sphinx/admin/properties.rst b/presto-docs/src/main/sphinx/admin/properties.rst index 6ee4b3438314..b80d35a7975c 100644 --- a/presto-docs/src/main/sphinx/admin/properties.rst +++ b/presto-docs/src/main/sphinx/admin/properties.rst @@ -1136,4 +1136,14 @@ Query Manager Properties This property can be used to configure how long a query runs without contact from the client application, such as the CLI, before it's abandoned. -The corresponding session property is :ref:`admin/properties-session:\`\`query_client_timeout\`\``. \ No newline at end of file +The corresponding session property is :ref:`admin/properties-session:\`\`query_client_timeout\`\``. + +``query.max-queued-time`` +^^^^^^^^^^^^^^^^^^^^^^^^^ + +* **Type:** ``Duration`` +* **Default value:** ``100d`` + +Use to configure how long a query can be queued before it is terminated. + +The corresponding session property is :ref:`admin/properties-session:\`\`query_max_queued_time\`\``. \ No newline at end of file diff --git a/presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java b/presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java index 810d2cbf5cca..046746ac4edf 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java +++ b/presto-main-base/src/main/java/com/facebook/presto/SystemSessionProperties.java @@ -115,6 +115,7 @@ public final class SystemSessionProperties public static final String QUERY_MAX_BROADCAST_MEMORY = "query_max_broadcast_memory"; public static final String QUERY_MAX_TOTAL_MEMORY = "query_max_total_memory"; public static final String QUERY_MAX_TOTAL_MEMORY_PER_NODE = "query_max_total_memory_per_node"; + public static final String QUERY_MAX_QUEUED_TIME = "query_max_queued_time"; public static final String QUERY_MAX_EXECUTION_TIME = "query_max_execution_time"; public static final String QUERY_MAX_RUN_TIME = "query_max_run_time"; public static final String RESOURCE_OVERCOMMIT = "resource_overcommit"; @@ -569,6 +570,15 @@ public SystemSessionProperties( false, value -> Duration.valueOf((String) value), Duration::toString), + new PropertyMetadata<>( + QUERY_MAX_QUEUED_TIME, + "Maximum Queued time of a query", + VARCHAR, + Duration.class, + queryManagerConfig.getQueryMaxQueuedTime(), + false, + value -> Duration.valueOf((String) value), + Duration::toString), new PropertyMetadata<>( QUERY_MAX_EXECUTION_TIME, "Maximum execution time of a query", @@ -2188,6 +2198,11 @@ public static Duration getQueryMaxRunTime(Session session) return session.getSystemProperty(QUERY_MAX_RUN_TIME, Duration.class); } + public static Duration getQueryMaxQueuedTime(Session session) + { + return session.getSystemProperty(QUERY_MAX_QUEUED_TIME, Duration.class); + } + public static Duration getQueryMaxExecutionTime(Session session) { return session.getSystemProperty(QUERY_MAX_EXECUTION_TIME, Duration.class); diff --git a/presto-main-base/src/main/java/com/facebook/presto/dispatcher/FailedDispatchQuery.java b/presto-main-base/src/main/java/com/facebook/presto/dispatcher/FailedDispatchQuery.java index b3dbc66fd6f4..ab2eb972af2d 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/dispatcher/FailedDispatchQuery.java +++ b/presto-main-base/src/main/java/com/facebook/presto/dispatcher/FailedDispatchQuery.java @@ -156,6 +156,12 @@ public long getCreateTimeInMillis() return basicQueryInfo.getQueryStats().getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return basicQueryInfo.getQueryStats().getQueuedTime(); + } + @Override public long getExecutionStartTimeInMillis() { diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/AccessControlCheckerExecution.java b/presto-main-base/src/main/java/com/facebook/presto/execution/AccessControlCheckerExecution.java index cf204e015785..93f8f47f582c 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/AccessControlCheckerExecution.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/AccessControlCheckerExecution.java @@ -145,6 +145,12 @@ public long getCreateTimeInMillis() return stateMachine.getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return stateMachine.getQueuedTime(); + } + @Override public long getExecutionStartTimeInMillis() { diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/DataDefinitionExecution.java b/presto-main-base/src/main/java/com/facebook/presto/execution/DataDefinitionExecution.java index 49c22ac63e36..972c33ed6939 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/DataDefinitionExecution.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/DataDefinitionExecution.java @@ -124,6 +124,12 @@ public long getCreateTimeInMillis() return stateMachine.getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return stateMachine.getQueuedTime(); + } + @Override public long getExecutionStartTimeInMillis() { diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryManagerConfig.java b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryManagerConfig.java index 5d73177e47a3..c7f91fb0b00f 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryManagerConfig.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryManagerConfig.java @@ -74,6 +74,7 @@ public class QueryManagerConfig private String queryExecutionPolicy = "all-at-once"; private Duration queryMaxRunTime = new Duration(100, TimeUnit.DAYS); + private Duration queryMaxQueuedTime = new Duration(100, TimeUnit.DAYS); private Duration queryMaxExecutionTime = new Duration(100, TimeUnit.DAYS); private Duration queryMaxCpuTime = new Duration(1_000_000_000, TimeUnit.DAYS); @@ -431,6 +432,19 @@ public QueryManagerConfig setQueryMaxRunTime(Duration queryMaxRunTime) return this; } + @NotNull + public Duration getQueryMaxQueuedTime() + { + return queryMaxQueuedTime; + } + + @Config("query.max-queued-time") + public QueryManagerConfig setQueryMaxQueuedTime(Duration queryMaxQueuedTime) + { + this.queryMaxQueuedTime = queryMaxQueuedTime; + return this; + } + @NotNull public Duration getQueryMaxExecutionTime() { diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryStateMachine.java b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryStateMachine.java index 46442b3af09f..7596bf3f29d0 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryStateMachine.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryStateMachine.java @@ -57,6 +57,7 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import io.airlift.units.Duration; import javax.annotation.Nullable; import javax.annotation.concurrent.GuardedBy; @@ -1025,6 +1026,11 @@ public long getCreateTimeInMillis() return queryStateTimer.getCreateTimeInMillis(); } + public Duration getQueuedTime() + { + return queryStateTimer.getQueuedTime(); + } + public long getExecutionStartTimeInMillis() { return queryStateTimer.getExecutionStartTimeInMillis(); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryTracker.java b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryTracker.java index d6290b664cf2..31091e78bb44 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/QueryTracker.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/QueryTracker.java @@ -43,6 +43,7 @@ import static com.facebook.presto.SystemSessionProperties.getQueryClientTimeout; import static com.facebook.presto.SystemSessionProperties.getQueryMaxExecutionTime; +import static com.facebook.presto.SystemSessionProperties.getQueryMaxQueuedTime; import static com.facebook.presto.SystemSessionProperties.getQueryMaxRunTime; import static com.facebook.presto.execution.QueryLimit.Source.QUERY; import static com.facebook.presto.execution.QueryLimit.Source.RESOURCE_GROUP; @@ -211,15 +212,17 @@ public long getQueriesKilledDueToTooManyTask() } /** - * Enforce query max runtime/execution time limits + * Enforce query max runtime/queued/execution time limits */ - private void enforceTimeLimits() + @VisibleForTesting + void enforceTimeLimits() { for (T query : queries.values()) { if (query.isDone()) { continue; } Duration queryMaxRunTime = getQueryMaxRunTime(query.getSession()); + Duration queryMaxQueuedTime = getQueryMaxQueuedTime(query.getSession()); QueryLimit queryMaxExecutionTime = getMinimum( createDurationLimit(getQueryMaxExecutionTime(query.getSession()), QUERY), query.getResourceGroupQueryLimits() @@ -227,6 +230,10 @@ private void enforceTimeLimits() .map(rgLimit -> createDurationLimit(rgLimit, RESOURCE_GROUP)).orElse(null)); long executionStartTime = query.getExecutionStartTimeInMillis(); long createTimeInMillis = query.getCreateTimeInMillis(); + long queuedTimeInMillis = query.getQueuedTime().toMillis(); + if (queuedTimeInMillis > queryMaxQueuedTime.toMillis()) { + query.fail(new PrestoException(EXCEEDED_TIME_LIMIT, "Query exceeded maximum queued time limit of " + queryMaxQueuedTime)); + } if (executionStartTime > 0 && (executionStartTime + queryMaxExecutionTime.getLimit().toMillis()) < currentTimeMillis()) { query.fail( new PrestoException(EXCEEDED_TIME_LIMIT, @@ -399,6 +406,8 @@ public interface TrackedQuery long getCreateTimeInMillis(); + Duration getQueuedTime(); + long getExecutionStartTimeInMillis(); long getLastHeartbeatInMillis(); diff --git a/presto-main-base/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java b/presto-main-base/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java index f6b55ac0a8ab..0f9047967bb4 100644 --- a/presto-main-base/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java +++ b/presto-main-base/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java @@ -341,6 +341,12 @@ public long getCreateTimeInMillis() return stateMachine.getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return stateMachine.getQueuedTime(); + } + /** * For a query that has started executing, returns the timestamp when this query started executing * Otherwise returns a {@link Optional#empty()} diff --git a/presto-main-base/src/test/java/com/facebook/presto/execution/MockQueryExecution.java b/presto-main-base/src/test/java/com/facebook/presto/execution/MockQueryExecution.java index f3da03ad2874..88a1ba2f7f0a 100644 --- a/presto-main-base/src/test/java/com/facebook/presto/execution/MockQueryExecution.java +++ b/presto-main-base/src/test/java/com/facebook/presto/execution/MockQueryExecution.java @@ -26,6 +26,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; +import static io.airlift.units.Duration.succinctDuration; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + public class MockQueryExecution implements QueryExecution { @@ -179,6 +182,12 @@ public long getCreateTimeInMillis() return 0L; } + @Override + public Duration getQueuedTime() + { + return succinctDuration(0, MILLISECONDS); + } + @Override public long getExecutionStartTimeInMillis() { diff --git a/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryManagerConfig.java b/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryManagerConfig.java index 4d06388452f2..4769b669c338 100644 --- a/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryManagerConfig.java +++ b/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryManagerConfig.java @@ -62,6 +62,7 @@ public void testDefaults() .setRemoteTaskMaxCallbackThreads(Runtime.getRuntime().availableProcessors()) .setQueryExecutionPolicy("all-at-once") .setQueryMaxRunTime(new Duration(100, TimeUnit.DAYS)) + .setQueryMaxQueuedTime(new Duration(100, TimeUnit.DAYS)) .setQueryMaxExecutionTime(new Duration(100, TimeUnit.DAYS)) .setQueryMaxCpuTime(new Duration(1_000_000_000, TimeUnit.DAYS)) .setQueryMaxScanRawInputBytes(new DataSize(1000, PETABYTE)) @@ -115,6 +116,7 @@ public void testExplicitPropertyMappings() .put("query.remote-task.max-callback-threads", "11") .put("query.execution-policy", "phased") .put("query.max-run-time", "2h") + .put("query.max-queued-time", "1h") .put("query.max-execution-time", "3h") .put("query.max-cpu-time", "2d") .put("query.max-scan-raw-input-bytes", "1MB") @@ -167,6 +169,7 @@ public void testExplicitPropertyMappings() .setRemoteTaskMaxCallbackThreads(11) .setQueryExecutionPolicy("phased") .setQueryMaxRunTime(new Duration(2, TimeUnit.HOURS)) + .setQueryMaxQueuedTime(new Duration(1, TimeUnit.HOURS)) .setQueryMaxExecutionTime(new Duration(3, TimeUnit.HOURS)) .setQueryMaxCpuTime(new Duration(2, TimeUnit.DAYS)) .setQueryMaxScanRawInputBytes(new DataSize(1, MEGABYTE)) diff --git a/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryTrackerQueuedTime.java b/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryTrackerQueuedTime.java new file mode 100644 index 000000000000..37b5521ac3b6 --- /dev/null +++ b/presto-main-base/src/test/java/com/facebook/presto/execution/TestQueryTrackerQueuedTime.java @@ -0,0 +1,353 @@ +/* + * Licensed 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 com.facebook.presto.execution; + +import com.facebook.presto.Session; +import com.facebook.presto.SystemSessionProperties; +import com.facebook.presto.execution.QueryTracker.TrackedQuery; +import com.facebook.presto.spi.PrestoException; +import com.facebook.presto.spi.QueryId; +import com.facebook.presto.spi.resourceGroups.ResourceGroupQueryLimits; +import io.airlift.units.Duration; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.util.Optional; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import static com.facebook.presto.SessionTestUtils.TEST_SESSION; +import static com.facebook.presto.spi.StandardErrorCode.EXCEEDED_TIME_LIMIT; +import static io.airlift.units.Duration.succinctDuration; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +@Test(singleThreaded = true) +public class TestQueryTrackerQueuedTime +{ + private ScheduledExecutorService executor; + private QueryTracker queryTracker; + + @BeforeMethod + public void setUp() + { + executor = newSingleThreadScheduledExecutor(); + QueryManagerConfig config = new QueryManagerConfig(); + queryTracker = new QueryTracker<>(config, executor, Optional.empty()); + queryTracker.start(); + } + + @AfterMethod + public void tearDown() + { + if (queryTracker != null) { + queryTracker.stop(); + } + if (executor != null) { + executor.shutdownNow(); + } + } + + @Test + public void testQueryExceedsQueuedTimeLimit() + throws Exception + { + // Create a session with 1 second queued time limit + Session session = Session.builder(TEST_SESSION) + .setSystemProperty(SystemSessionProperties.QUERY_MAX_QUEUED_TIME, "1s") + .build(); + + AtomicReference failureException = new AtomicReference<>(); + AtomicBoolean queryFailed = new AtomicBoolean(false); + + // Create a mock query that has been queued for 2 seconds (exceeds limit) + long currentTime = System.currentTimeMillis(); + MockTrackedQuery query = new MockTrackedQuery( + new QueryId("test_query_1"), + session, + currentTime - 2000, // Created 2 seconds ago + 0, // Not started execution yet + currentTime, + failureException, + queryFailed); + + queryTracker.addQuery(query); + + // Manually trigger time limit enforcement + queryTracker.enforceTimeLimits(); + + // Verify the query was failed due to exceeding queued time limit + assertTrue(queryFailed.get(), "Query should have been failed"); + assertNotNull(failureException.get(), "Failure exception should be set"); + assertEquals(failureException.get().getErrorCode(), EXCEEDED_TIME_LIMIT.toErrorCode()); + assertTrue(failureException.get().getMessage().contains("Query exceeded maximum queued time limit")); + } + + @Test + public void testQueryWithinQueuedTimeLimit() + throws Exception + { + // Create a session with 5 second queued time limit + Session session = Session.builder(TEST_SESSION) + .setSystemProperty(SystemSessionProperties.QUERY_MAX_QUEUED_TIME, "5s") + .build(); + + AtomicReference failureException = new AtomicReference<>(); + AtomicBoolean queryFailed = new AtomicBoolean(false); + + // Create a mock query that has been queued for 1 second (within limit) + long currentTime = System.currentTimeMillis(); + MockTrackedQuery query = new MockTrackedQuery( + new QueryId("test_query_2"), + session, + currentTime - 1000, // Created 1 second ago + 0, // Not started execution yet + currentTime, + failureException, + queryFailed); + + queryTracker.addQuery(query); + + // Manually trigger time limit enforcement + queryTracker.enforceTimeLimits(); + + // Verify the query was not failed + assertFalse(queryFailed.get(), "Query should not have been failed"); + } + + @Test + public void testQueryStartedExecutionQueuedTimeCalculation() + throws Exception + { + // Create a session with 1 second queued time limit + Session session = Session.builder(TEST_SESSION) + .setSystemProperty(SystemSessionProperties.QUERY_MAX_QUEUED_TIME, "1s") + .build(); + + AtomicReference failureException = new AtomicReference<>(); + AtomicBoolean queryFailed = new AtomicBoolean(false); + + // Create a mock query that was queued for 2 seconds but started execution + long currentTime = System.currentTimeMillis(); + MockTrackedQuery query = new MockTrackedQuery( + new QueryId("test_query_3"), + session, + currentTime - 3000, // Created 3 seconds ago + currentTime - 1000, // Started execution 1 second ago (queued for 2 seconds) + currentTime, + failureException, + queryFailed); + + queryTracker.addQuery(query); + + // Manually trigger time limit enforcement + queryTracker.enforceTimeLimits(); + + // Verify the query was failed because it was queued for 2 seconds (exceeds 1s limit) + assertTrue(queryFailed.get(), "Query should have been failed"); + assertNotNull(failureException.get(), "Failure exception should be set"); + assertEquals(failureException.get().getErrorCode(), EXCEEDED_TIME_LIMIT.toErrorCode()); + assertTrue(failureException.get().getMessage().contains("Query exceeded maximum queued time limit")); + } + + @Test + public void testQueryStartedExecutionWithinQueuedTimeLimit() + throws Exception + { + // Create a session with 5 second queued time limit + Session session = Session.builder(TEST_SESSION) + .setSystemProperty(SystemSessionProperties.QUERY_MAX_QUEUED_TIME, "5s") + .build(); + + AtomicReference failureException = new AtomicReference<>(); + AtomicBoolean queryFailed = new AtomicBoolean(false); + + // Create a mock query that was queued for 1 second and started execution + long currentTime = System.currentTimeMillis(); + MockTrackedQuery query = new MockTrackedQuery( + new QueryId("test_query_4"), + session, + currentTime - 2000, // Created 2 seconds ago + currentTime - 1000, // Started execution 1 second ago (queued for 1 second) + currentTime, + failureException, + queryFailed); + + queryTracker.addQuery(query); + + // Manually trigger time limit enforcement + queryTracker.enforceTimeLimits(); + + // Verify the query was not failed + assertFalse(queryFailed.get(), "Query should not have been failed"); + } + + @Test + public void testCompletedQueryNotChecked() + throws Exception + { + // Create a session with 1 second queued time limit + Session session = Session.builder(TEST_SESSION) + .setSystemProperty(SystemSessionProperties.QUERY_MAX_QUEUED_TIME, "1s") + .build(); + + AtomicReference failureException = new AtomicReference<>(); + AtomicBoolean queryFailed = new AtomicBoolean(false); + + // Create a mock query that is already completed + long currentTime = System.currentTimeMillis(); + MockTrackedQuery query = new MockTrackedQuery( + new QueryId("test_query_5"), + session, + currentTime - 5000, // Created 5 seconds ago + 0, // Not started execution yet + currentTime, + failureException, + queryFailed); + query.setDone(true); // Mark as completed + + queryTracker.addQuery(query); + + // Manually trigger time limit enforcement + queryTracker.enforceTimeLimits(); + + // Verify the completed query was not failed + assertFalse(queryFailed.get(), "Completed query should not be checked for time limits"); + } + + private static class MockTrackedQuery + implements TrackedQuery + { + private final QueryId queryId; + private final Session session; + private final long createTimeInMillis; + private final long executionStartTimeInMillis; + private final long lastHeartbeatInMillis; + private final AtomicReference failureException; + private final AtomicBoolean queryFailed; + private boolean done; + + public MockTrackedQuery( + QueryId queryId, + Session session, + long createTimeInMillis, + long executionStartTimeInMillis, + long lastHeartbeatInMillis, + AtomicReference failureException, + AtomicBoolean queryFailed) + { + this.queryId = queryId; + this.session = session; + this.createTimeInMillis = createTimeInMillis; + this.executionStartTimeInMillis = executionStartTimeInMillis; + this.lastHeartbeatInMillis = lastHeartbeatInMillis; + this.failureException = failureException; + this.queryFailed = queryFailed; + } + + public void setDone(boolean done) + { + this.done = done; + } + + @Override + public QueryId getQueryId() + { + return queryId; + } + + @Override + public boolean isDone() + { + return done; + } + + @Override + public Session getSession() + { + return session; + } + + @Override + public long getCreateTimeInMillis() + { + return createTimeInMillis; + } + + @Override + public Duration getQueuedTime() + { + long queuedTimeInMillis; + if (executionStartTimeInMillis > 0) { + queuedTimeInMillis = executionStartTimeInMillis - createTimeInMillis; + } + else { + queuedTimeInMillis = System.currentTimeMillis() - createTimeInMillis; + } + return succinctDuration(queuedTimeInMillis, MILLISECONDS); + } + + @Override + public long getExecutionStartTimeInMillis() + { + return executionStartTimeInMillis; + } + + @Override + public long getLastHeartbeatInMillis() + { + return lastHeartbeatInMillis; + } + + @Override + public long getEndTimeInMillis() + { + return done ? System.currentTimeMillis() : 0; + } + + @Override + public Optional getResourceGroupQueryLimits() + { + return Optional.empty(); + } + + @Override + public void fail(Throwable cause) + { + if (cause instanceof PrestoException) { + failureException.set((PrestoException) cause); + } + queryFailed.set(true); + done = true; + } + + @Override + public void pruneExpiredQueryInfo() + { + // No-op for test + } + + @Override + public void pruneFinishedQueryInfo() + { + // No-op for test + } + } +} diff --git a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQuery.java b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQuery.java index eb65385df75f..d740fbe1f8f0 100644 --- a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQuery.java +++ b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQuery.java @@ -279,6 +279,12 @@ public long getCreateTimeInMillis() return stateMachine.getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return stateMachine.getQueuedTime(); + } + @Override public long getExecutionStartTimeInMillis() { diff --git a/presto-tests/src/test/java/com/facebook/presto/tests/TestQueryManager.java b/presto-tests/src/test/java/com/facebook/presto/tests/TestQueryManager.java index 034b22b5d669..eff5d1803b18 100644 --- a/presto-tests/src/test/java/com/facebook/presto/tests/TestQueryManager.java +++ b/presto-tests/src/test/java/com/facebook/presto/tests/TestQueryManager.java @@ -380,6 +380,12 @@ public long getCreateTimeInMillis() return info.getQueryStats().getCreateTimeInMillis(); } + @Override + public Duration getQueuedTime() + { + return info.getQueryStats().getQueuedTime(); + } + @Override public Duration getTotalCpuTime() {