From 2dcbe28d5ab0f8cd80329037e79f2cfe81124a60 Mon Sep 17 00:00:00 2001 From: Geunee Date: Thu, 4 Jul 2024 00:44:13 +0900 Subject: [PATCH] Query Editor Draft 2 (#20) --- .../domain/cluster/ClusterQueryCommander.java | 27 ++-- .../cluster/ClusterQueryCommanderArgs.java | 47 +++++++ .../cluster/ClusterQueryCommanderResult.java | 8 +- .../cluster/{ => query}/ClusterQueryApi.java | 16 +-- .../cluster/query/ClusterQueryRequest.java | 42 ++++++ .../cluster/query/ClusterQueryResponse.java | 25 ++++ .../cluster/components/query/query-editor.js | 126 +++++++++++++++--- 7 files changed, 248 insertions(+), 43 deletions(-) create mode 100644 cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderArgs.java rename cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/{ => query}/ClusterQueryApi.java (81%) create mode 100644 cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryRequest.java create mode 100644 cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryResponse.java diff --git a/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommander.java b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommander.java index e839b6ca..13fa5e3f 100644 --- a/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommander.java +++ b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommander.java @@ -32,12 +32,12 @@ @Service public class ClusterQueryCommander { - public ClusterQueryCommanderResult execute(CqlSession session, String query, String nextTokenParam) { - SimpleStatement statement = SimpleStatement.builder(query) - .setPageSize(2) // 10 per pages - .setTimeout(Duration.ofSeconds(3)) // 3s timeout - .setPagingState(StringUtils.isNotBlank(nextTokenParam) ? Bytes.fromHexString(nextTokenParam) : null) - .setTracing(false) + public ClusterQueryCommanderResult execute(CqlSession session, ClusterQueryCommanderArgs args) { + SimpleStatement statement = SimpleStatement.builder(args.getQuery()) + .setPageSize(args.getPageSize()) // 10 per pages + .setTimeout(Duration.ofSeconds(args.getTimeoutSeconds())) // 3s timeout + .setPagingState(StringUtils.isNotBlank(args.getCursor()) ? Bytes.fromHexString(args.getCursor()) : null) + .setTracing(args.isTrace()) .build(); //.setConsistencyLevel(ConsistencyLevel.ONE); @@ -45,7 +45,6 @@ public ClusterQueryCommanderResult execute(CqlSession session, String query, Str ColumnDefinitions definitions = resultSet.getColumnDefinitions(); - //log.info("+ Page 1 has {} items", resultSet.getAvailableWithoutFetching()); Iterator page1Iter = resultSet.iterator(); List> rows = new ArrayList<>(); @@ -57,20 +56,24 @@ public ClusterQueryCommanderResult execute(CqlSession session, String query, Str List columnNames = new ArrayList<>(); for (ColumnDefinition definition : definitions) { + //TODO : 컬럼 정보 이름 외에도 추가하기 columnNames.add(definition.getName().asCql(true)); } - QueryTrace queryTrace = resultSet.getExecutionInfo().getQueryTrace(); - log.info("query Trace : {}", queryTrace.getTracingId()); - for (TraceEvent event : queryTrace.getEvents()) { - log.info("event : {}", event); + if (args.isTrace()) { + QueryTrace queryTrace = resultSet.getExecutionInfo().getQueryTrace(); + log.info("query Trace : {}", queryTrace.getTracingId()); + for (TraceEvent event : queryTrace.getEvents()) { + log.info("event : {}", event); + //TODO : 추적값 담기 + } } return ClusterQueryCommanderResult.builder() .wasApplied(resultSet.wasApplied()) .columnNames(columnNames) .rows(rows) - .nextToken(Bytes.toHexString(pagingStateAsBytes)) + .nextCursor(pagingStateAsBytes != null ? Bytes.toHexString(pagingStateAsBytes) : null) .build(); } diff --git a/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderArgs.java b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderArgs.java new file mode 100644 index 00000000..dad595ee --- /dev/null +++ b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderArgs.java @@ -0,0 +1,47 @@ +package kr.hakdang.cadio.core.domain.cluster; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * ClusterQueryCommanderArgs + * + * @author akageun + * @since 2024-07-03 + */ +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ClusterQueryCommanderArgs { + private String query; + private String cursor; + private int pageSize; + private int timeoutSeconds; + private boolean trace = false; + + @Builder + public ClusterQueryCommanderArgs(String query, String cursor, Integer pageSize, Integer timeoutSeconds, boolean trace) { + if (pageSize == null || pageSize <= 0) { + pageSize = 50; + } + + if (pageSize > 500) { + throw new RuntimeException("pageSize 500 over"); + } + + if (timeoutSeconds == null || timeoutSeconds <= 0) { + timeoutSeconds = 3; //default 3 + } + + if (timeoutSeconds > 60) { + throw new RuntimeException("timeout 60 over"); + } + + this.query = query; + this.cursor = cursor; + this.pageSize = pageSize; + this.timeoutSeconds = timeoutSeconds; + this.trace = trace; + } +} diff --git a/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderResult.java b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderResult.java index e5553173..76b6373e 100644 --- a/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderResult.java +++ b/cadio-core/src/main/java/kr/hakdang/cadio/core/domain/cluster/ClusterQueryCommanderResult.java @@ -20,13 +20,15 @@ public class ClusterQueryCommanderResult { private boolean wasApplied; private List columnNames; private List> rows; - private String nextToken; + private String previousCursor; + private String nextCursor; @Builder - public ClusterQueryCommanderResult(boolean wasApplied, List columnNames, List> rows, String nextToken) { + public ClusterQueryCommanderResult(boolean wasApplied, List columnNames, List> rows, String previousCursor, String nextCursor) { this.wasApplied = wasApplied; this.columnNames = columnNames; this.rows = rows; - this.nextToken = nextToken; + this.previousCursor = previousCursor; + this.nextCursor = nextCursor; } } diff --git a/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/ClusterQueryApi.java b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryApi.java similarity index 81% rename from cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/ClusterQueryApi.java rename to cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryApi.java index 32e45a73..2a834f7d 100644 --- a/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/ClusterQueryApi.java +++ b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryApi.java @@ -1,4 +1,4 @@ -package kr.hakdang.cadio.web.route.cluster; +package kr.hakdang.cadio.web.route.cluster.query; import com.datastax.oss.driver.api.core.CqlSession; import kr.hakdang.cadio.core.domain.cluster.ClusterQueryCommander; @@ -18,8 +18,6 @@ import java.util.HashMap; import java.util.Map; -import static java.util.Collections.emptyMap; - /** * ClusterQueryApi * @@ -38,13 +36,12 @@ public class ClusterQueryApi extends BaseSample { public ApiResponse> clusterQueryCommand( @RequestBody ClusterQueryRequest request ) { - Map map = new HashMap<>(); try (CqlSession session = makeSession()) { //TODO : interface 작업할 때 facade layer 로 변경 예정 - ClusterQueryCommanderResult result1 = clusterQueryCommander.execute(session, request.getQuery(), request.getNextToken()); + ClusterQueryCommanderResult result1 = clusterQueryCommander.execute(session, request.makeArgs()); map.put("wasApplied", result1.isWasApplied()); - map.put("nextToken", result1.getNextToken()); + map.put("nextCursor", result1.getNextCursor()); map.put("rows", result1.getRows()); map.put("columnNames", result1.getColumnNames()); } catch (Exception e) { @@ -55,11 +52,4 @@ public ApiResponse> clusterQueryCommand( return ApiResponse.ok(map); } - - @Getter - @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class ClusterQueryRequest { - private String query; - private String nextToken; - } } diff --git a/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryRequest.java b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryRequest.java new file mode 100644 index 00000000..c553e66b --- /dev/null +++ b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryRequest.java @@ -0,0 +1,42 @@ +package kr.hakdang.cadio.web.route.cluster.query; + +import kr.hakdang.cadio.core.domain.cluster.ClusterQueryCommanderArgs; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * ClusterQueryRequest + * + * @author akageun + * @since 2024-07-03 + */ +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ClusterQueryRequest { + private String query; + private String cursor; + private int pageSize; + private int timeoutSeconds; + private boolean trace = false; + + @Builder + public ClusterQueryRequest(String query, String cursor, int pageSize, int timeoutSeconds, boolean trace) { + this.query = query; + this.cursor = cursor; + this.pageSize = pageSize; + this.timeoutSeconds = timeoutSeconds; + this.trace = trace; + } + + public ClusterQueryCommanderArgs makeArgs() { + return ClusterQueryCommanderArgs.builder() + .query(query) + .cursor(cursor) + .pageSize(pageSize) + .timeoutSeconds(timeoutSeconds) + .trace(trace) + .build(); + } +} diff --git a/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryResponse.java b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryResponse.java new file mode 100644 index 00000000..c4198344 --- /dev/null +++ b/cadio-web/src/main/java/kr/hakdang/cadio/web/route/cluster/query/ClusterQueryResponse.java @@ -0,0 +1,25 @@ +package kr.hakdang.cadio.web.route.cluster.query; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; +import java.util.Map; + +/** + * ClusterQueryResponse + * + * @author akageun + * @since 2024-07-03 + */ +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ClusterQueryResponse { + private boolean wasApplied; + private List columnNames; + private List> rows; + private String nextToken; + + +} diff --git a/cadio-web/src/main/webapp/src/pages/cluster/components/query/query-editor.js b/cadio-web/src/main/webapp/src/pages/cluster/components/query/query-editor.js index 0e49ebd2..fd34252b 100644 --- a/cadio-web/src/main/webapp/src/pages/cluster/components/query/query-editor.js +++ b/cadio-web/src/main/webapp/src/pages/cluster/components/query/query-editor.js @@ -4,10 +4,12 @@ import axios from "axios"; const QueryEditor = () => { + const [queryLoading, setQueryLoading] = useState(false) + const [queryParam, setQueryParam] = useState( { query: "SELECT * FROM testdb.test_table_1;", - nextToken: "", + nextCursor: "", } ); @@ -17,30 +19,50 @@ const QueryEditor = () => { columnNames: [], }) - const queryExecute = () => { - setQueryResult({ - wasApplied: null, - rows: [], - columnNames: [], - }) + const queryExecute = (cursor) => { + if (!queryParam.query) { + alert("쿼리를 입력해 주세요.") + return; + } + + if (cursor === null) { + setQueryResult({ + wasApplied: null, + rows: [], + columnNames: [], + }) + } + + setQueryLoading(true); axios({ method: "POST", url: "/api/cassandra/cluster/query", data: { query: queryParam.query, - nextToken: queryParam.nextToken, + pageSize: 2, + timeoutSeconds: 3, + cursor: cursor, }, }).then((response) => { console.log("response : ", response); + + setQueryParam(t => { + return { + ...t, + nextCursor: response.data.result.nextCursor + } + }) + setQueryResult({ wasApplied: response.data.result.wasApplied, - rows: response.data.result.rows, + rows: [...queryResult.rows, ...response.data.result.rows], columnNames: response.data.result.columnNames, }) }).catch((error) => { }).finally(() => { + setQueryLoading(false); }) } @@ -48,8 +70,23 @@ const QueryEditor = () => { <>
- +
+
+
{/*
*/} @@ -67,7 +104,58 @@ const QueryEditor = () => { {/*
*/}
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
+
+ {/*현재는 단일 쿼리만 실행 가능하도록*/}