Skip to content

Commit f615c00

Browse files
authored
Merge pull request #221 from jumpserver/pr@new_terminal@feat_console_stability
fix(console): improve cancellation
2 parents e7b82c2 + 1a2fd10 commit f615c00

3 files changed

Lines changed: 47 additions & 15 deletions

File tree

backend/framework/src/main/java/org/jumpserver/chen/framework/console/QueryConsole.java

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import com.alibaba.druid.sql.parser.ParserException;
44
import com.google.gson.Gson;
5+
import com.google.gson.JsonParseException;
56
import lombok.extern.slf4j.Slf4j;
67
import org.apache.commons.lang3.StringUtils;
78
import org.jumpserver.chen.framework.console.action.DataViewAction;
89
import org.jumpserver.chen.framework.console.action.QueryConsoleAction;
10+
import org.jumpserver.chen.framework.console.action.SQLChunkData;
911
import org.jumpserver.chen.framework.console.dataview.DataView;
1012
import org.jumpserver.chen.framework.console.dataview.QueryDataViewTableEditContextFactory;
1113
import org.jumpserver.chen.framework.console.dataview.UpdateDataView;
@@ -359,16 +361,27 @@ private void onAction(QueryConsoleAction action) {
359361
private int expectedChunks = -1;
360362

361363
private void handleSQLChunk(QueryConsoleAction action) {
362-
var data = (Map<String, Object>) action.getData();
363-
var chunk = (String) data.get("chunk");
364-
var index = (Integer) data.get("index");
365-
var total = (Integer) data.get("total");
364+
SQLChunkData data;
365+
try {
366+
data = GSON.fromJson(GSON.toJson(action.getData()), SQLChunkData.class);
367+
} catch (JsonParseException e) {
368+
this.getConsoleLogger().error("invalid sql chunk");
369+
this.resetSQLChunks();
370+
return;
371+
}
366372

367-
if (chunk == null || index == null || total == null || total <= 0) {
373+
if (data == null
374+
|| data.getChunk() == null
375+
|| data.getIndex() == null
376+
|| data.getTotal() == null
377+
|| data.getTotal() <= 0) {
368378
this.getConsoleLogger().error("invalid sql chunk");
369379
this.resetSQLChunks();
370380
return;
371381
}
382+
var chunk = data.getChunk();
383+
var index = data.getIndex();
384+
var total = data.getTotal();
372385
if (expectedChunks == -1) {
373386
expectedChunks = total;
374387
}
@@ -617,9 +630,9 @@ public void onCancel() {
617630
this.getState().setExecutionStatus(EXECUTION_STATUS_CANCELLED);
618631
try {
619632
var plan = this.currentPlan;
620-
if (plan != null && plan.getStatement() != null) {
633+
if (plan != null) {
621634
plan.cancel();
622-
this.getConsoleLogger().error("cancel query: %s", plan.getTargetSQL());
635+
this.getConsoleLogger().warn("cancel query: %s", plan.getTargetSQL());
623636
}
624637
} catch (SQLException | RuntimeException e) {
625638
log.error("cancel failed ", e);
@@ -775,9 +788,9 @@ public void onSQL(String sql) {
775788
} catch (SQLException e) {
776789
if (!StringUtils.equals(this.getState().getExecutionStatus(), EXECUTION_STATUS_CANCELLED)) {
777790
this.getState().setExecutionStatus(EXECUTION_STATUS_ERROR);
791+
this.getConsoleLogger().error("%s: %s", MessageUtils.get("ExecuteError"), e.getMessage());
792+
this.getPacketIO().sendPacket("message", Message.error(MessageUtils.get("ExecuteError"), e.getMessage()));
778793
}
779-
this.getConsoleLogger().error("%s: %s", MessageUtils.get("ExecuteError"), e.getMessage());
780-
this.getPacketIO().sendPacket("message", Message.error(MessageUtils.get("ExecuteError"), e.getMessage()));
781794
} finally {
782795
if (StringUtils.equals(this.getState().getExecutionStatus(), EXECUTION_STATUS_RUNNING)) {
783796
this.getState().setExecutionStatus(EXECUTION_STATUS_SUCCESS);
@@ -893,15 +906,13 @@ private DataView runSingleSQL(String sql, ACLResult aclResult) throws SQLExcepti
893906
.createPlan(SQL.of(sourceSQL));
894907
plan.setAclResult(aclResult);
895908
plan.setSqlQueryParams(sqlQueryParams);
896-
plan.generateTargetSQL();
897-
this.getConsoleLogger().info("execute sql: %s", plan.getTargetSQL());
898-
899909
this.currentPlan = plan;
900-
901910
this.getState().setCanCancel(true);
902911
this.stateManager.commit();
903912

904913
try {
914+
plan.generateTargetSQL();
915+
this.getConsoleLogger().info("execute sql: %s", plan.getTargetSQL());
905916
var result = plan.executeWithAudit();
906917
this.getConsoleLogger().success(result);
907918
return result;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.jumpserver.chen.framework.console.action;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class SQLChunkData {
7+
private String chunk;
8+
private Integer index;
9+
private Integer total;
10+
}

backend/framework/src/main/java/org/jumpserver/chen/framework/datasource/sql/SQLExecutePlan.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class SQLExecutePlan {
2727
private String targetSQL;
2828
private final DbType druidDbType;
2929
private volatile Statement statement;
30+
private volatile boolean cancelled;
3031
private Connection connection;
3132
private ACLResult aclResult;
3233

@@ -85,7 +86,10 @@ public SQLQueryResult executeWithAudit() throws SQLException {
8586
}
8687

8788

88-
public Statement createStatement() throws SQLException {
89+
public synchronized Statement createStatement() throws SQLException {
90+
if (this.cancelled) {
91+
throw new SQLException(MessageUtils.get("ExecutionCanceled"));
92+
}
8993
if (this.statement == null || this.statement.isClosed()) {
9094
this.statement = this.connection.createStatement();
9195
}
@@ -97,7 +101,14 @@ public SQLStatement getTargetSQLStatement() {
97101
}
98102

99103
public void cancel() throws SQLException {
100-
this.statement.cancel();
104+
Statement currentStatement;
105+
synchronized (this) {
106+
this.cancelled = true;
107+
currentStatement = this.statement;
108+
}
109+
if (currentStatement != null && !currentStatement.isClosed()) {
110+
currentStatement.cancel();
111+
}
101112
}
102113

103114
public void close() {

0 commit comments

Comments
 (0)