Browse Source

Pull request #9176: REPORT-73318【设计器环境监测】服务器finedb有脏数据,设计器远程切换,过程很慢且没有自动监测弹窗

Merge in DESIGN/design from ~HARRISON/design:feature/x to feature/x

* commit '0c20e0c051f72b7ee5d19f5fd6006b8c3c116ab1':
  REPORT-73318【设计器环境监测】服务器finedb有脏数据,设计器远程切换,过程很慢且没有自动监测弹窗 1-简化操作,不区分 设计器/服务器 启动。只在设计器启动后进行检测 2-切换环境的检测。切换环境后上次的任务需要停止执行。 3-FineDB 检测从捕获检测,切换到全量检测
feature/x
Harrison 2 years ago
parent
commit
ba971ed55c
  1. 105
      designer-base/src/main/java/com/fr/env/detect/EnvDetectorCenter.java
  2. 98
      designer-base/src/main/java/com/fr/env/detect/impl/FineDbDirtyDetector.java
  3. 110
      designer-base/src/main/java/com/fr/env/detect/impl/converter/FineDbDirtyConverter.java

105
designer-base/src/main/java/com/fr/env/detect/EnvDetectorCenter.java vendored

@ -17,59 +17,43 @@ import com.fr.event.Event;
import com.fr.event.EventDispatcher; import com.fr.event.EventDispatcher;
import com.fr.event.Listener; import com.fr.event.Listener;
import com.fr.event.Null; import com.fr.event.Null;
import com.fr.start.server.EmbedServerEvent; import com.fr.stable.core.UUID;
import com.fr.task.Once; import com.fr.task.Once;
import com.fr.update.delay.DelayHelper; import com.fr.update.delay.DelayHelper;
import com.fr.workspace.Workspace; import com.fr.workspace.Workspace;
import com.fr.workspace.WorkspaceEvent; import com.fr.workspace.WorkspaceEvent;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
* 环境检测中心 * 环境检测中心
* 如果环境检测 ->
* *
* created by Harrison on 2022/05/27 * created by Harrison on 2022/05/27
**/ **/
public class EnvDetectorCenter { public class EnvDetectorCenter {
private final Listener<Null> AFTER_START_LISTENER = new Listener<Null>() {
@Override
public void on(Event event, Null param) {
if (isSameProcess(DetectorProcess.SERVER_LAUNCH)) {
stop();
}
}
};
private final Listener<Null> BEFORE_START_LISTENER = new Listener<Null>() {
@Override
public void on(Event event, Null param) {
PROCESS.set(DetectorProcess.SERVER_LAUNCH);
start();
}
};
private final Listener<Null> START_UP_COMPLETE_LISTENER = new Listener<Null>() { private final Listener<Null> START_UP_COMPLETE_LISTENER = new Listener<Null>() {
@Override @Override
public void on(Event event, Null param) { public void on(Event event, Null param) {
if (isSameProcess(DetectorProcess.DESIGN_LAUNCH)) { // startup 的监听,执行一次即可
EventDispatcher.stopListen(this);
stop(); stop();
} }
}
}; };
private final Listener<Workspace> AFTER_SWITCH_LISTENER = new Listener<Workspace>() { private final Listener<Workspace> AFTER_SWITCH_LISTENER = new Listener<Workspace>() {
@Override @Override
public void on(Event event, Workspace param) { public void on(Event event, Workspace param) {
if (isSameProcess(DetectorProcess.DESIGN_LAUNCH)) {
stop(); stop();
} }
}
}; };
private final Once launchOnce = new Once(() -> { private final Once launchOnce = new Once(() -> {
@ -82,6 +66,13 @@ public class EnvDetectorCenter {
private final AtomicReference<DetectorProcess> PROCESS = new AtomicReference<>(); private final AtomicReference<DetectorProcess> PROCESS = new AtomicReference<>();
/**
* 当前还有什么动作未执行
* 如果切换环境这里的动作是要被清空的
* 从而防止切换环境后, 上一个动作的环境延续过来
*/
private final Set<String> pendingActions = new HashSet<>();
public static EnvDetectorCenter getInstance() { public static EnvDetectorCenter getInstance() {
return EnvDetectorCenterHolder.INSTANCE; return EnvDetectorCenterHolder.INSTANCE;
} }
@ -105,7 +96,6 @@ public class EnvDetectorCenter {
PROCESS.set(DetectorProcess.DESIGN_LAUNCH); PROCESS.set(DetectorProcess.DESIGN_LAUNCH);
launchOnce.run(); launchOnce.run();
listen();
} }
@ -114,7 +104,9 @@ public class EnvDetectorCenter {
*/ */
public void destroy() { public void destroy() {
stopListen(); // 清空
pendingActions.clear();
// 重置内容 // 重置内容
DetectorBridge.getInstance().reset(); DetectorBridge.getInstance().reset();
// 关闭逻辑 // 关闭逻辑
@ -123,20 +115,6 @@ public class EnvDetectorCenter {
PROCESS.set(null); PROCESS.set(null);
} }
/**
* 当前的流程符合预期
* 什么情况下不符合
* design.start -> server.start -> design.end -> server.end
* 这个时候 design.end 就不会触发等待服务器启动后才触发
*
* @param process 检测流程
* @return /
*/
private boolean isSameProcess(DetectorProcess process) {
return PROCESS.compareAndSet(process, null);
}
/** /**
* 启动 * 启动
*/ */
@ -153,13 +131,23 @@ public class EnvDetectorCenter {
// 结束 // 结束
DetectorBridge.getInstance().stop(); DetectorBridge.getInstance().stop();
// id值
String uuid = UUID.randomUUID().toString();
// 确认当前的 action 是否有效
Supplier<Boolean> validAction = () -> pendingActions.contains(uuid);
// 30s后执行 // 30s后执行
DelayHelper.delayCall(EnvDetectorCenter.class.getName(), () -> { Runnable detectorAction = () -> {
// 如果当前没开启,则直接返回 // 如果当前没开启,则直接返回
if (!EnvDetectorConfig.getInstance().isEnabled()) { if (!EnvDetectorConfig.getInstance().isEnabled()) {
return; return;
} }
// 如果当前不包含这个 id, 就不执行
if (!validAction.get()) {
return;
}
Stream<DetectorResult> resultStream = DetectorBridge.getInstance().detect(); Stream<DetectorResult> resultStream = DetectorBridge.getInstance().detect();
// 展示效果 // 展示效果
@ -174,10 +162,25 @@ public class EnvDetectorCenter {
} }
UIUtil.invokeLaterIfNeeded(() -> { UIUtil.invokeLaterIfNeeded(() -> {
// 如果当前不包含这个 id, 就不执行
if (!validAction.get()) {
return;
}
NotificationDialog dialog = new NotificationDialog(properties, notificationModels); NotificationDialog dialog = new NotificationDialog(properties, notificationModels);
dialog.open(); dialog.open();
}); });
}, 30, TimeUnit.SECONDS);
// 执行完移除
pendingActions.remove(uuid);
};
// 添加
pendingActions.add(uuid);
DelayHelper.delayCall(EnvDetectorCenter.class.getName(), detectorAction, 30, TimeUnit.SECONDS);
} }
@ -208,18 +211,6 @@ public class EnvDetectorCenter {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private void listen() {
// 内置服务器监听
EventDispatcher.listen(EmbedServerEvent.BeforeStart, BEFORE_START_LISTENER);
EventDispatcher.listen(EmbedServerEvent.AfterStart, AFTER_START_LISTENER);
}
private void stopListen() {
EventDispatcher.stopListen(BEFORE_START_LISTENER);
EventDispatcher.stopListen(AFTER_START_LISTENER);
}
private enum DetectorProcess { private enum DetectorProcess {
@ -227,15 +218,5 @@ public class EnvDetectorCenter {
* 设计器启动 * 设计器启动
*/ */
DESIGN_LAUNCH, DESIGN_LAUNCH,
/**
* 服务器启动
*/
SERVER_LAUNCH,
/**
* 环境切换
*/
ENV_SWITCH
} }
} }

98
designer-base/src/main/java/com/fr/env/detect/impl/FineDbDirtyDetector.java vendored

@ -1,22 +1,106 @@
package com.fr.env.detect.impl; package com.fr.env.detect.impl;
import com.fr.env.detect.base.CatchExceptionDetector; import com.fr.config.ConfigContext;
import com.fr.config.Configuration;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.env.detect.base.AbstractExceptionDetector;
import com.fr.env.detect.base.DetectorConstants;
import com.fr.env.detect.bean.DetectorResult;
import com.fr.env.detect.bean.DetectorType; import com.fr.env.detect.bean.DetectorType;
import com.fr.env.detect.impl.converter.FineDbDirtyConverter; import com.fr.env.detect.bean.ExceptionSolution;
import com.fr.env.detect.thowable.ThrowableStore; import com.fr.env.detect.bean.Message;
import com.fr.env.detect.bean.SolutionAction;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.org.hibernate.exception.GenericJDBCException;
import javax.swing.JOptionPane;
import java.util.Iterator;
import java.util.function.Function;
/** /**
* created by Harrison on 2022/05/25 * created by Harrison on 2022/05/25
**/ **/
public class FineDbDirtyDetector extends CatchExceptionDetector { public class FineDbDirtyDetector extends AbstractExceptionDetector {
public FineDbDirtyDetector() { public FineDbDirtyDetector() {
this(ThrowableStore.getInstance());
super(DetectorType.FINE_DB_DIRTY);
}
@Override
public DetectorResult detect() {
Iterator<String> tableNames = ConfigContext.getConfigNames();
while (tableNames.hasNext()) {
String tableName = tableNames.next();
Class<? extends Configuration> configClass = ConfigContext.getConfigClass(tableName);
Configuration configuration = ConfigContext.getConfigInstance(configClass);
try {
// 尝试获取每一个值
configuration.mirror();
} catch (Throwable e) {
Function<Throwable, Boolean> isDirtyExFunction = throwable -> {
while (throwable != null) {
if (throwable instanceof GenericJDBCException) {
return true;
}
throwable = throwable.getCause();
} }
return false;
};
boolean isDirtyEx = isDirtyExFunction.apply(e);
public FineDbDirtyDetector(ThrowableStore throwableStore) { if (isDirtyEx) {
DetectorType detectorType = DetectorType.FINE_DB_DIRTY;
DetectorResult.DetectorResultBuilder builder = DetectorResult
.builder()
.withType(detectorType);
super(DetectorType.FINE_DB_DIRTY, throwableStore, new FineDbDirtyConverter()); String tipsLocale = Toolkit.i18nText(detectorType.getTipsLocale(), tableName);
String solutionLocale = detectorType.getSolutionLocale();
ExceptionSolution exceptionSolution = new ExceptionSolution(new Message.Link(Toolkit.i18nText(solutionLocale, DetectorConstants.FINE_DB_HELP_LINK), DetectorConstants.FINE_DB_HELP_LINK), new SolutionAction() {
@Override
public String name() {
return Toolkit.i18nText("Fine-Design_Basic_Reset_Immediately");
} }
@Override
public void run() {
boolean success = false;
try {
ResourceIOUtils.copy(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME),
StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_BAK_NAME));
success = ResourceIOUtils.delete(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
// todo 最好的逻辑是,这里应该和 UI 隔离开的
if (!success) {
FineJOptionPane.showMessageDialog(null,
Toolkit.i18nText("Fine-Design_Error_Finedb_Backup_Reset_Result",
ResourceIOUtils.getRealPath(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME))),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.ERROR_MESSAGE);
}
}
});
builder.withTips(tipsLocale)
.withSolution(exceptionSolution)
.withLog(Toolkit.i18nText(detectorType.getLogLocale(), tableName));
return builder.build();
}
}
}
return DetectorResult.normal(DetectorType.FINE_DB_DIRTY);
}
} }

110
designer-base/src/main/java/com/fr/env/detect/impl/converter/FineDbDirtyConverter.java vendored

@ -1,110 +0,0 @@
package com.fr.env.detect.impl.converter;
import com.fr.config.ConfigContext;
import com.fr.config.Configuration;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.env.detect.base.DetectorConstants;
import com.fr.env.detect.bean.DetectorResult;
import com.fr.env.detect.bean.DetectorType;
import com.fr.env.detect.bean.ExceptionSolution;
import com.fr.env.detect.bean.Message;
import com.fr.env.detect.bean.SolutionAction;
import com.fr.env.detect.thowable.ThrowableConverter;
import com.fr.io.utils.ResourceIOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StableUtils;
import com.fr.stable.project.ProjectConstants;
import com.fr.third.org.hibernate.exception.GenericJDBCException;
import org.jetbrains.annotations.Nullable;
import javax.swing.JOptionPane;
import java.util.Iterator;
/**
* 脏数据检测
*
* created by Harrison on 2022/05/25
**/
public class FineDbDirtyConverter implements ThrowableConverter {
@Override
public boolean accept(Throwable throwable) {
Throwable sign = throwable;
while (sign != null) {
if (sign.getClass() == GenericJDBCException.class) {
return true;
}
sign = sign.getCause();
}
return false;
}
/**
* 根据堆栈确认是否是从配置中发出来的异常
* 如果是则找到对应的配置的表
* 输出信息
*
* @param throwable 异常
* @return 检测结果
*/
@Override
public @Nullable DetectorResult convert(Throwable throwable) {
Iterator<String> tableNames = ConfigContext.getConfigNames();
while (tableNames.hasNext()) {
String tableName = tableNames.next();
Class<? extends Configuration> configClass = ConfigContext.getConfigClass(tableName);
Configuration configuration = ConfigContext.getConfigInstance(configClass);
try {
// 尝试获取每一个值
configuration.mirror();
} catch (Throwable e) {
DetectorType detectorType = DetectorType.FINE_DB_DIRTY;
DetectorResult.DetectorResultBuilder builder = DetectorResult.builder()
.withType(detectorType);
String tipsLocale = Toolkit.i18nText(detectorType.getTipsLocale(), tableName);
String solutionLocale = detectorType.getSolutionLocale();
ExceptionSolution exceptionSolution = new ExceptionSolution(new Message.Link(Toolkit.i18nText(solutionLocale, DetectorConstants.FINE_DB_HELP_LINK), DetectorConstants.FINE_DB_HELP_LINK), new SolutionAction() {
@Override
public String name() {
return Toolkit.i18nText("Fine-Design_Basic_Reset_Immediately");
}
@Override
public void run() {
boolean success = false;
try {
ResourceIOUtils.copy(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME),
StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_BAK_NAME));
success = ResourceIOUtils.delete(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME));
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
// todo 最好的逻辑是,这里应该和 UI 隔离开的
if (!success) {
FineJOptionPane.showMessageDialog(null,
Toolkit.i18nText("Fine-Design_Error_Finedb_Backup_Reset_Result",
ResourceIOUtils.getRealPath(StableUtils.pathJoin(ProjectConstants.EMBED_DB_DIRECTORY, ProjectConstants.FINE_DB_NAME))),
Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.ERROR_MESSAGE);
}
}
});
builder.withTips(tipsLocale)
.withSolution(exceptionSolution)
.withLog(Toolkit.i18nText(detectorType.getLogLocale(), tableName));
return builder.build();
}
}
return DetectorResult.normal(DetectorType.FINE_DB_DIRTY);
}
}
Loading…
Cancel
Save