Browse Source

REPORT-99451 远程设计专项-功能侧优化-模板锁定优化

feature/x
roger 12 months ago
parent
commit
28d21883d2
  1. 132
      designer-base/src/main/java/com/fr/design/RPCConnectHandlerCenter.java
  2. 45
      designer-base/src/main/java/com/fr/design/lock/TemplateLockInfoReSave.java
  3. 2
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  4. 74
      designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java
  5. 4
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

132
designer-base/src/main/java/com/fr/design/RPCConnectHandlerCenter.java

@ -0,0 +1,132 @@
package com.fr.design;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.util.UIUtil;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpGet;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import com.fr.workspace.base.WorkspaceConstants;
import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.engine.exception.WorkspaceConnectionException;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
/**
* RPC连接处理中心
*
* @author Roger
* @since 11.0
* Created on 2023/12/13
*/
public class RPCConnectHandlerCenter {
private static volatile boolean alerting = false;
private static final int TIMEOUT = 5000;
/**
* 开启事件监听
*/
public static void startListener() {
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.listen(WorkspaceEvent.LostConnect, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace workspace) {
//暂时先不做重连处理,3次RPC连接失败后提示切换工作目录
showRPCDisconnectDialog();
}
});
}
}
/**
* 弹窗提示连接断开
*/
public static void showRPCDisconnectDialog() {
UIUtil.invokeLaterIfNeeded(RPCConnectHandlerCenter::showDialog);
}
/**
* 连接检测从DesignerSocketIO中移过来的
*
* @param info 连接信息
* @return 是否连接成功
*/
public static boolean checkRPCConnect(WorkspaceConnectionInfo info) {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(StableUtils.pathJoin(info.getUrl(), WorkspaceConstants.CONTROLLER_PREFIX, WorkspaceConstants.VT));
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectTimeout(TIMEOUT)
.setConnectionRequestTimeout(TIMEOUT)
.build();
httpGet.setConfig(requestConfig);
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
if (isErrorStatus(response.getStatusLine().getStatusCode())) {
//这边nginx做负载,服务器被kill掉,返回的是502,不会抛错,导致checkRPCConnect通过
//针对500-600的错误码加个判断,其他类型的状态码暂不考虑,如果有遇到再处理,不然怕影响范围大
throw new WorkspaceConnectionException("Response " + response.getStatusLine().toString());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
return false;
}
return true;
}
/**
* 提示连接已经断开如果已经在提示中了就直接返回
*/
private static void showDialog() {
if (alerting) {
return;
}
synchronized (RPCConnectHandlerCenter.class) {
if (alerting) {
return;
}
alerting = true;
try {
FineJOptionPane.showMessageDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"),
UIManager.getString("OptionPane.messageDialogTitle"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon"));
EnvChangeEntrance.getInstance().chooseEnv();
} finally {
alerting = false;
}
}
}
/**
* 错误状态码
* 5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误 这些错误可能是服务器本身的错误而不是请求出错代码 说明
* 500 (服务器内部错误) 服务器遇到错误无法完成请求
* 501 (尚未实施) 服务器不具备完成请求的功能 例如服务器无法识别请求方法时可能会返回此代码
* 502 (错误网关) 服务器作为网关或代理从上游服务器收到无效响应
* 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护) 通常这只是暂时状态
* 504 (网关超时) 服务器作为网关或代理但是没有及时从上游服务器收到请求
* 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本
*
* @param status 错误状态码
* @return 是否是错误状态码
*/
private static boolean isErrorStatus(int status) {
return status >= 500 && status <= 600;
}
}

45
designer-base/src/main/java/com/fr/design/lock/TemplateLockInfoReSave.java

@ -0,0 +1,45 @@
package com.fr.design.lock;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.JTemplate;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import com.fr.report.lock.LockInfoOperator;
import com.fr.stable.collections.CollectionUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent;
import java.util.List;
/**
* 更新模板锁信息
*
* @author Roger
* @since 11.0
* Created on 2023/12/11
*/
public class TemplateLockInfoReSave {
/**
* 启动监听
*/
public static void startListener() {
if (!WorkContext.getCurrent().isLocal()) {
EventDispatcher.listen(WorkspaceEvent.ReConnectSuccess, new Listener<Workspace>() {
@Override
public void on(Event event, Workspace workspace) {
List<JTemplate<?, ?>> templates = HistoryTemplateListCache.getInstance().getHistoryList();
if (CollectionUtils.isEmpty(templates)) {
return;
}
String[] paths = templates.stream().map(JTemplate::getPath).toArray(String[]::new);
String[] lockedPath = WorkContext.getCurrent().get(LockInfoOperator.class).lockTemplates(paths);
FineLoggerFactory.getLogger().warn("template lock failed:{}", String.join(";", lockedPath));
}
});
}
}
}

2
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -1060,7 +1060,7 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
// 过滤掉本地文件 // 过滤掉本地文件
boolean localFile = getEditingFILE() instanceof FileFILE; boolean localFile = getEditingFILE() instanceof FileFILE;
boolean inconsistent = !localFile && getEditingFILE().exists() boolean inconsistent = !localFile && getEditingFILE().exists()
&& !WorkContext.getCurrent().get(LockInfoOperator.class).isConsistentLock(getEditingFILE().getPath()); && !WorkContext.getCurrent().get(LockInfoOperator.class).consistentCheckAndLockIfNecessary(getEditingFILE().getPath());
if (inconsistent) { if (inconsistent) {
throw new InconsistentLockException(); throw new InconsistentLockException();
} }

74
designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java

@ -2,15 +2,13 @@ package com.fr.design.mainframe.socketio;
import com.fr.config.RemoteConfigEvent; import com.fr.config.RemoteConfigEvent;
import com.fr.design.DesignerEnvManager; import com.fr.design.DesignerEnvManager;
import com.fr.design.EnvChangeEntrance; import com.fr.design.RPCConnectHandlerCenter;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.env.DesignerWorkspaceInfo; import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.DesignerWorkspaceInfoContext; import com.fr.design.env.DesignerWorkspaceInfoContext;
import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.LocaleLinkProvider; import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.loghandler.DesignerLogger; import com.fr.design.mainframe.loghandler.DesignerLogger;
import com.fr.design.mainframe.share.ui.base.MouseClickListener; import com.fr.design.mainframe.share.ui.base.MouseClickListener;
import com.fr.design.mainframe.toast.DesignerToastMsgUtil; import com.fr.design.mainframe.toast.DesignerToastMsgUtil;
@ -21,18 +19,11 @@ import com.fr.event.EventDispatcher;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
import com.fr.serialization.SerializerHelper; import com.fr.serialization.SerializerHelper;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import com.fr.stable.StableUtils;
import com.fr.third.apache.logging.log4j.core.LogEvent; import com.fr.third.apache.logging.log4j.core.LogEvent;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpGet;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import com.fr.workspace.Workspace; import com.fr.workspace.Workspace;
import com.fr.workspace.base.WorkspaceConstants; import com.fr.workspace.base.WorkspaceConstants;
import com.fr.workspace.connect.WorkspaceConnectionInfo; import com.fr.workspace.connect.WorkspaceConnectionInfo;
import com.fr.workspace.engine.exception.WorkspaceConnectionException;
import com.fr.workspace.server.socket.CustomLogEvent; import com.fr.workspace.server.socket.CustomLogEvent;
import com.fr.workspace.server.socket.LogEventConverter; import com.fr.workspace.server.socket.LogEventConverter;
import io.socket.client.IO; import io.socket.client.IO;
@ -40,9 +31,7 @@ import io.socket.client.Socket;
import io.socket.emitter.Emitter; import io.socket.emitter.Emitter;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.UIManager;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Cursor; import java.awt.Cursor;
@ -76,7 +65,6 @@ public class DesignerSocketIO {
private static Status status = Status.Disconnected; private static Status status = Status.Disconnected;
private static Timer disConnectHintTimer = null; private static Timer disConnectHintTimer = null;
private static long disConnectHintTimerDelay = 3000; private static long disConnectHintTimerDelay = 3000;
private static final int TIMEOUT = 5000;
//维护一个当前工作环境的websocket连接信息列表 //维护一个当前工作环境的websocket连接信息列表
private static ConnectionInfo[] connectionInfos; private static ConnectionInfo[] connectionInfos;
//维护一个关于uri列表的计数器 //维护一个关于uri列表的计数器
@ -205,10 +193,10 @@ public class DesignerSocketIO {
}; };
private static void dealWithSocketDisconnect() { private static void dealWithSocketDisconnect() {
if (checkRPCConnect()) { if (RPCConnectHandlerCenter.checkRPCConnect(getConnectionInfo())) {
showSocketDisconnectToast(); showSocketDisconnectToast();
} else { } else {
showRPCDisconnectDialog(); RPCConnectHandlerCenter.showRPCDisconnectDialog();
} }
} }
@ -245,62 +233,6 @@ public class DesignerSocketIO {
return jPanel; return jPanel;
} }
private static void showRPCDisconnectDialog() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
FineJOptionPane.showMessageDialog(
DesignerContext.getDesignerFrame(),
Toolkit.i18nText("Fine-Design_Basic_Remote_Disconnected"),
UIManager.getString("OptionPane.messageDialogTitle"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon"));
EnvChangeEntrance.getInstance().chooseEnv();
}
});
}
private static boolean checkRPCConnect() {
CloseableHttpClient httpclient = HttpClients.createDefault();
WorkspaceConnectionInfo info = getConnectionInfo();
HttpGet httpGet = new HttpGet(StableUtils.pathJoin(info.getUrl(), WorkspaceConstants.CONTROLLER_PREFIX, WorkspaceConstants.VT));
RequestConfig requestConfig = RequestConfig
.custom()
.setConnectTimeout(TIMEOUT)
.setConnectionRequestTimeout(TIMEOUT)
.build();
httpGet.setConfig(requestConfig);
try {
CloseableHttpResponse response = httpclient.execute(httpGet);
if (isErrorStatus(response.getStatusLine().getStatusCode())) {
//这边nginx做负载,服务器被kill掉,返回的是502,不会抛错,导致checkRPCConnect通过
//针对500-600的错误码加个判断,其他类型的状态码暂不考虑,如果有遇到再处理,不然怕影响范围大
throw new WorkspaceConnectionException("Response " + response.getStatusLine().toString());
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
return false;
}
return true;
}
/**
* 错误状态码
* 5xx(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误 这些错误可能是服务器本身的错误而不是请求出错代码 说明
* 500 (服务器内部错误) 服务器遇到错误无法完成请求
* 501 (尚未实施) 服务器不具备完成请求的功能 例如服务器无法识别请求方法时可能会返回此代码
* 502 (错误网关) 服务器作为网关或代理从上游服务器收到无效响应
* 503 (服务不可用) 服务器目前无法使用(由于超载或停机维护) 通常这只是暂时状态
* 504 (网关超时) 服务器作为网关或代理但是没有及时从上游服务器收到请求
* 505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本
*
* @param status 错误状态码
* @return 是否是错误状态码
*/
private static boolean isErrorStatus(int status) {
return status >= 500 && status <= 600;
}
//配置变更监听器 //配置变更监听器
private static final Emitter.Listener modifyConfig = new Emitter.Listener() { private static final Emitter.Listener modifyConfig = new Emitter.Listener() {
@Override @Override

4
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -17,6 +17,7 @@ import com.fr.decision.webservice.v10.plugin.helper.category.impl.PluginResource
import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader; import com.fr.decision.webservice.v10.plugin.helper.category.impl.UpmResourceLoader;
import com.fr.design.DesignerEnvManager; import com.fr.design.DesignerEnvManager;
import com.fr.design.ExtraDesignClassManager; import com.fr.design.ExtraDesignClassManager;
import com.fr.design.RPCConnectHandlerCenter;
import com.fr.design.actions.NewFormAction; import com.fr.design.actions.NewFormAction;
import com.fr.design.actions.core.ActionFactory; import com.fr.design.actions.core.ActionFactory;
import com.fr.design.actions.insert.cell.BiasCellAction; import com.fr.design.actions.insert.cell.BiasCellAction;
@ -51,6 +52,7 @@ import com.fr.design.javascript.EmailPane;
import com.fr.design.javascript.JavaScriptImplPane; import com.fr.design.javascript.JavaScriptImplPane;
import com.fr.design.javascript.ParameterJavaScriptPane; import com.fr.design.javascript.ParameterJavaScriptPane;
import com.fr.design.javascript.ProcessTransitionAdapter; import com.fr.design.javascript.ProcessTransitionAdapter;
import com.fr.design.lock.TemplateLockInfoReSave;
import com.fr.design.login.DesignerLoginType; import com.fr.design.login.DesignerLoginType;
import com.fr.design.login.guide.DesignerGuideHelper; import com.fr.design.login.guide.DesignerGuideHelper;
import com.fr.design.login.message.DesignerMessageHelper; import com.fr.design.login.message.DesignerMessageHelper;
@ -214,6 +216,8 @@ public class DesignerActivator extends Activator implements Prepare {
AlphaFineHelper.switchConfig4Locale(); AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner()); RecoverManager.register(new RecoverForDesigner());
WidgetThemeListenerStarter.start(); WidgetThemeListenerStarter.start();
TemplateLockInfoReSave.startListener();
RPCConnectHandlerCenter.startListener();
}, DesignerStartupPool.common()); }, DesignerStartupPool.common());
CompletableFuture<Void> resourcePrepare = CompletableFuture.runAsync(() -> { CompletableFuture<Void> resourcePrepare = CompletableFuture.runAsync(() -> {

Loading…
Cancel
Save