This is an automated email from the ASF dual-hosted git repository. mhubail pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit e76b460b3578475beb30882e6303da4307adff7b Author: Ali Alsuliman <ali.al.solai...@gmail.com> AuthorDate: Wed Jan 24 14:16:32 2024 -0800 [ASTERIXDB-3343][API] Add servlet to get completed requests - user model changes: no - storage format changes: no - interface changes: yes Details: - Add new servlet 'CompletedRequestsServlet' to retrieve the completed requests similar to what completed_requests() returns. - Make CcQueryCancellationServlet implement GET to retrieve the active requests similar to what active_requests() returns. - Rename CcQueryCancellationServlet to ActiveRequestsServlet. Change-Id: I9bd395a75970abe01a4fab0a88abcae4df881564 Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18138 Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Ali Alsuliman <ali.al.solai...@gmail.com> Reviewed-by: Murtadha Hubail <mhub...@apache.org> (cherry picked from commit 88c25279458badf088ae36ecef2bf50a66d9638c) Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18109 Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> --- .../asterix/translator/BaseClientRequest.java | 3 +- .../apache/asterix/translator/ClientRequest.java | 2 +- .../api/http/server/AbstractRequestsServlet.java | 60 ++++++++++++++++++++++ ...tionServlet.java => ActiveRequestsServlet.java} | 19 ++++--- .../api/http/server/CompletedRequestsServlet.java | 38 ++++++++++++++ .../http/server/NCQueryCancellationServlet.java | 2 +- .../asterix/hyracks/bootstrap/CCApplication.java | 4 +- .../http/servlet/QueryCancellationServletTest.java | 6 +-- .../apache/asterix/common/api/IClientRequest.java | 10 +++- 9 files changed, 127 insertions(+), 17 deletions(-) diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/BaseClientRequest.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/BaseClientRequest.java index 99cda09f7c..db633e6873 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/BaseClientRequest.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/BaseClientRequest.java @@ -93,7 +93,8 @@ public abstract class BaseClientRequest implements IClientRequest { return JSONUtil.convertNodeUnchecked(asJson()); } - protected ObjectNode asJson() { + @Override + public ObjectNode asJson() { ObjectNode json = JSONUtil.createObject(); json.put("uuid", requestReference.getUuid()); json.put("requestTime", new ADateTime(requestReference.getTime()).toSimpleString()); diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ClientRequest.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ClientRequest.java index c19bb026a5..4f193660f9 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ClientRequest.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/ClientRequest.java @@ -76,7 +76,7 @@ public class ClientRequest extends BaseClientRequest { } @Override - protected ObjectNode asJson() { + public ObjectNode asJson() { ObjectNode json = super.asJson(); json.put("jobId", jobId != null ? jobId.toString() : null); json.put("statement", statement); diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractRequestsServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractRequestsServlet.java new file mode 100644 index 0000000000..285c4c837b --- /dev/null +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/AbstractRequestsServlet.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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 org.apache.asterix.api.http.server; + +import java.util.Collection; +import java.util.concurrent.ConcurrentMap; + +import org.apache.asterix.common.api.IClientRequest; +import org.apache.asterix.common.dataflow.ICcApplicationContext; +import org.apache.hyracks.http.api.IServletRequest; +import org.apache.hyracks.http.api.IServletResponse; +import org.apache.hyracks.http.server.AbstractServlet; +import org.apache.hyracks.http.server.utils.HttpUtil; +import org.apache.hyracks.util.JSONUtil; + +import com.fasterxml.jackson.databind.node.ArrayNode; + +import io.netty.handler.codec.http.HttpResponseStatus; + +public abstract class AbstractRequestsServlet extends AbstractServlet { + + protected final ICcApplicationContext appCtx; + + public AbstractRequestsServlet(ConcurrentMap<String, Object> ctx, ICcApplicationContext appCtx, String... paths) { + super(ctx, paths); + this.appCtx = appCtx; + } + + @Override + protected void get(IServletRequest request, IServletResponse response) throws Exception { + ArrayNode requestsJson = JSONUtil.createArray(); + Collection<IClientRequest> requests = getRequests(); + for (IClientRequest req : requests) { + requestsJson.add(req.asJson()); + } + HttpUtil.setContentType(response, HttpUtil.ContentType.APPLICATION_JSON, request); + response.setStatus(HttpResponseStatus.OK); + JSONUtil.writeNode(response.writer(), requestsJson); + response.writer().flush(); + } + + abstract Collection<IClientRequest> getRequests(); + +} diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ActiveRequestsServlet.java similarity index 83% rename from asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java rename to asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ActiveRequestsServlet.java index 7ba28675b6..7e00e9ae93 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CcQueryCancellationServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ActiveRequestsServlet.java @@ -19,6 +19,7 @@ package org.apache.asterix.api.http.server; import java.io.IOException; +import java.util.Collection; import java.util.concurrent.ConcurrentMap; import org.apache.asterix.api.http.server.QueryServiceRequestParameters.Parameter; @@ -27,7 +28,6 @@ import org.apache.asterix.common.api.IRequestTracker; import org.apache.asterix.common.dataflow.ICcApplicationContext; import org.apache.hyracks.http.api.IServletRequest; import org.apache.hyracks.http.api.IServletResponse; -import org.apache.hyracks.http.server.AbstractServlet; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -35,24 +35,27 @@ import org.apache.logging.log4j.Logger; import io.netty.handler.codec.http.HttpResponseStatus; /** - * The servlet provides a REST API for cancelling an on-going query. + * The servlet provides a REST API for getting the running queries or cancelling an on-going one. */ -public class CcQueryCancellationServlet extends AbstractServlet { +public class ActiveRequestsServlet extends AbstractRequestsServlet { public static final String REQUEST_UUID_PARAM_NAME = "request_id"; private static final Logger LOGGER = LogManager.getLogger(); - private final ICcApplicationContext appCtx; - public CcQueryCancellationServlet(ConcurrentMap<String, Object> ctx, ICcApplicationContext appCtx, - String... paths) { - super(ctx, paths); - this.appCtx = appCtx; + public ActiveRequestsServlet(ConcurrentMap<String, Object> ctx, ICcApplicationContext appCtx, String... paths) { + super(ctx, appCtx, paths); + } + + @Override + public Collection<IClientRequest> getRequests() { + return appCtx.getRequestTracker().getRunningRequests(); } @Override protected void delete(IServletRequest request, IServletResponse response) throws IOException { String uuid = request.getParameter(REQUEST_UUID_PARAM_NAME); String clientCtxId = request.getParameter(Parameter.CLIENT_ID.str()); + LOGGER.debug("received cancel request, uuid={}, clientCtxId={}", uuid, clientCtxId); if (uuid == null && clientCtxId == null) { response.setStatus(HttpResponseStatus.BAD_REQUEST); return; diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CompletedRequestsServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CompletedRequestsServlet.java new file mode 100644 index 0000000000..92eacbb0fa --- /dev/null +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/CompletedRequestsServlet.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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 org.apache.asterix.api.http.server; + +import java.util.Collection; +import java.util.concurrent.ConcurrentMap; + +import org.apache.asterix.common.api.IClientRequest; +import org.apache.asterix.common.dataflow.ICcApplicationContext; + +public class CompletedRequestsServlet extends AbstractRequestsServlet { + + public CompletedRequestsServlet(ConcurrentMap<String, Object> ctx, ICcApplicationContext appCtx, String... paths) { + super(ctx, appCtx, paths); + } + + @Override + public Collection<IClientRequest> getRequests() { + return appCtx.getRequestTracker().getCompletedRequests(); + } + +} diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java index b2134dcfc6..5dd9430840 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/NCQueryCancellationServlet.java @@ -18,7 +18,7 @@ */ package org.apache.asterix.api.http.server; -import static org.apache.asterix.api.http.server.CcQueryCancellationServlet.REQUEST_UUID_PARAM_NAME; +import static org.apache.asterix.api.http.server.ActiveRequestsServlet.REQUEST_UUID_PARAM_NAME; import static org.apache.asterix.app.message.ExecuteStatementRequestMessage.DEFAULT_NC_TIMEOUT_MILLIS; import java.util.concurrent.ConcurrentMap; diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java index bc67823916..1b011aeb86 100644 --- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java +++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplication.java @@ -37,9 +37,9 @@ import java.util.ServiceLoader; import java.util.concurrent.ConcurrentMap; import org.apache.asterix.api.http.IQueryWebServerRegistrant; +import org.apache.asterix.api.http.server.ActiveRequestsServlet; import org.apache.asterix.api.http.server.ActiveStatsApiServlet; import org.apache.asterix.api.http.server.ApiServlet; -import org.apache.asterix.api.http.server.CcQueryCancellationServlet; import org.apache.asterix.api.http.server.ClusterApiServlet; import org.apache.asterix.api.http.server.ClusterControllerDetailsApiServlet; import org.apache.asterix.api.http.server.ConnectorApiServlet; @@ -315,7 +315,7 @@ public class CCApplication extends BaseCCApplication { ConcurrentMap<String, Object> ctx = server.ctx(); switch (key) { case Servlets.RUNNING_REQUESTS: - return new CcQueryCancellationServlet(ctx, appCtx, paths); + return new ActiveRequestsServlet(ctx, appCtx, paths); case Servlets.QUERY_STATUS: return new QueryStatusApiServlet(ctx, appCtx, paths); case Servlets.QUERY_RESULT: diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryCancellationServletTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryCancellationServletTest.java index 68fb9a8419..b38c366489 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryCancellationServletTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/api/http/servlet/QueryCancellationServletTest.java @@ -27,7 +27,7 @@ import static org.mockito.Mockito.when; import java.util.concurrent.ConcurrentHashMap; -import org.apache.asterix.api.http.server.CcQueryCancellationServlet; +import org.apache.asterix.api.http.server.ActiveRequestsServlet; import org.apache.asterix.api.http.server.ServletConstants; import org.apache.asterix.app.translator.RequestParameters; import org.apache.asterix.common.api.RequestReference; @@ -57,8 +57,8 @@ public class QueryCancellationServletTest { RequestTracker tracker = new RequestTracker(appCtx); Mockito.when(appCtx.getRequestTracker()).thenReturn(tracker); // Creates a query cancellation servlet. - CcQueryCancellationServlet cancellationServlet = - new CcQueryCancellationServlet(new ConcurrentHashMap<>(), appCtx, new String[] { "/" }); + ActiveRequestsServlet cancellationServlet = + new ActiveRequestsServlet(new ConcurrentHashMap<>(), appCtx, new String[] { "/" }); // Adds mocked Hyracks client connection into the servlet context. IHyracksClientConnection mockHcc = mock(IHyracksClientConnection.class); cancellationServlet.ctx().put(ServletConstants.HYRACKS_CONNECTION_ATTR, mockHcc); diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IClientRequest.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IClientRequest.java index 921fb64095..3157c64d29 100644 --- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IClientRequest.java +++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/api/IClientRequest.java @@ -21,6 +21,8 @@ package org.apache.asterix.common.api; import org.apache.asterix.common.dataflow.ICcApplicationContext; import org.apache.hyracks.api.exceptions.HyracksDataException; +import com.fasterxml.jackson.databind.node.ObjectNode; + public interface IClientRequest { enum State { @@ -86,7 +88,13 @@ public interface IClientRequest { void cancel(ICcApplicationContext appCtx) throws HyracksDataException; /** - * @return A json representation of this request + * @return A json string representation of this request */ String toJson(); + + /** + * @return A json node representation of this request + */ + ObjectNode asJson(); + }