diff --git a/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java b/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java index 6b5c6aacd0..6eef4b8d2c 100644 --- a/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java +++ b/backend/src/main/java/io/dataease/commons/constants/ParamConstants.java @@ -110,6 +110,8 @@ public interface ParamConstants { enum BASIC implements ParamConstants { FRONT_TIME_OUT("basic.frontTimeOut"), MSG_TIME_OUT("basic.msgTimeOut"), + DS_CHECK_INTERVAL("basic.dsCheckInterval"), + DS_CHECK_INTERVAL_TYPE("basic.dsCheckIntervalType"), DEFAULT_LOGIN_TYPE("basic.loginType"), OPEN_HOME_PAGE("ui.openHomePage"), diff --git a/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java b/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java index 4a4ca4f3b8..7038a03406 100644 --- a/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java +++ b/backend/src/main/java/io/dataease/controller/sys/response/BasicInfo.java @@ -22,5 +22,9 @@ public class BasicInfo implements Serializable { private String templateAccessKey; @ApiModelProperty("显示模板市场") private String openMarketPage; + @ApiModelProperty("数据源检测时间间隔") + private String dsCheckInterval; + @ApiModelProperty("数据源检测时间间隔类型") + private String dsCheckIntervalType; } diff --git a/backend/src/main/java/io/dataease/job/sechedule/Schedular.java b/backend/src/main/java/io/dataease/job/sechedule/Schedular.java index 6a1693e6ff..c6575cc218 100644 --- a/backend/src/main/java/io/dataease/job/sechedule/Schedular.java +++ b/backend/src/main/java/io/dataease/job/sechedule/Schedular.java @@ -22,9 +22,9 @@ public class Schedular { dataSetTableService.updateDatasetTableStatus(); } - @QuartzScheduled(cron = "0 0/30 * * * ?") + @QuartzScheduled(cron = "0 0/3 * * * ?") public void updateDatasourceStatus() { - datasourceService.updateDatasourceStatus(); + datasourceService.checkDatasourceJob(); } @QuartzScheduled(cron = "0 0/30 * * * ?") diff --git a/backend/src/main/java/io/dataease/listener/DataSourceInitStartListener.java b/backend/src/main/java/io/dataease/listener/DataSourceInitStartListener.java index d9c360d1a8..bc53c1b879 100644 --- a/backend/src/main/java/io/dataease/listener/DataSourceInitStartListener.java +++ b/backend/src/main/java/io/dataease/listener/DataSourceInitStartListener.java @@ -22,8 +22,10 @@ public class DataSourceInitStartListener implements ApplicationListener types() { Collection types = new ArrayList<>(); @@ -432,6 +447,24 @@ public class DatasourceService { } } + public void checkDatasourceJob() { + List qrtzSchedulerStates = qrtzSchedulerStateMapper.selectByExample(null); + List activeQrtzInstances = qrtzSchedulerStates.stream() + .filter(qrtzSchedulerState -> qrtzSchedulerState.getLastCheckinTime() + + qrtzSchedulerState.getCheckinInterval() + 1000 > utilMapper.currentTimestamp()) + .map(QrtzSchedulerStateKey::getInstanceName).collect(Collectors.toList()); + + + List taskInstances = extTaskInstanceMapper.select(); + taskInstances.forEach(taskInstance -> { + if (StringUtils.isNotEmpty(taskInstance.getQrtzInstance()) && !activeQrtzInstances.contains(taskInstance.getQrtzInstance().substring(0, taskInstance.getQrtzInstance().length() - 13))) { + TaskInstance update = new TaskInstance(); + update.setTaskId("Datasource_check_status"); + extTaskInstanceMapper.update(update); + } + }); + } + public void updateDatasourceStatus() { List datasources = datasourceMapper.selectByExampleWithBLOBs(new DatasourceExample()); datasources.forEach(datasource -> checkAndUpdateDatasourceStatus(datasource, true)); @@ -496,4 +529,57 @@ public class DatasourceService { DeMsgutil.sendMsg(userId, typeId, content, gson.toJson(param)); }); } + + public void updateDatasourceStatusJob(BasicInfo basicInfo, List parameters) { + String type = ""; + Integer interval = 30; + + boolean changeDsCheckTime = false; + basicInfo.getDsCheckInterval(); + basicInfo.getDsCheckIntervalType(); + for (SystemParameter parameter : parameters) { + if (parameter.getParamKey().equalsIgnoreCase("basic.dsCheckInterval") && !parameter.getParamValue().equalsIgnoreCase(basicInfo.getDsCheckInterval())) { + changeDsCheckTime = true; + interval = Integer.valueOf(parameter.getParamValue()); + } + if (parameter.getParamKey().equalsIgnoreCase("basic.dsCheckIntervalType") && !parameter.getParamValue().equalsIgnoreCase(basicInfo.getDsCheckInterval())) { + changeDsCheckTime = true; + type = parameter.getParamValue(); + } + } + if(!changeDsCheckTime){ + return; + } + addJob(type, interval); + } + + private void addJob(String type, Integer interval) { + String cron = ""; + switch (type){ + case "hour": + cron = "0 0 0/hour * * ? *".replace("hour", interval.toString()); + break; + default: + cron = "0 0/minute * * * ? *".replace("minute", interval.toString()); + } + + GlobalTaskEntity globalTask = new GlobalTaskEntity(); + globalTask.setCron(cron); + globalTask.setCreateTime(System.currentTimeMillis()); + globalTask.setJobKey("Datasource_check_status"); + globalTask.setTaskName("Datasource check status"); + globalTask.setTaskType("dsTaskHandler"); + globalTask.setStartTime(System.currentTimeMillis()); + try { + scheduleService.addSchedule(globalTask); + }catch (Exception e){ + e.printStackTrace(); + } + } + + public void initDsCheckJob(){ + BasicInfo basicInfo = systemParameterService.basicInfo(); + addJob(basicInfo.getDsCheckIntervalType(), Integer.valueOf(basicInfo.getDsCheckInterval())); + } + } diff --git a/backend/src/main/java/io/dataease/service/system/SystemParameterService.java b/backend/src/main/java/io/dataease/service/system/SystemParameterService.java index 015858320e..0b70c4ccd1 100644 --- a/backend/src/main/java/io/dataease/service/system/SystemParameterService.java +++ b/backend/src/main/java/io/dataease/service/system/SystemParameterService.java @@ -8,7 +8,6 @@ import io.dataease.controller.sys.response.BasicInfo; import io.dataease.dto.SystemParameterDTO; import io.dataease.exception.DataEaseException; import io.dataease.plugins.common.base.domain.FileMetadata; -import io.dataease.plugins.common.base.domain.SysParamAssist; import io.dataease.plugins.common.base.domain.SystemParameter; import io.dataease.plugins.common.base.domain.SystemParameterExample; import io.dataease.plugins.common.base.mapper.SystemParameterMapper; @@ -17,10 +16,11 @@ import io.dataease.plugins.xpack.cas.dto.CasSaveResult; import io.dataease.plugins.xpack.cas.service.CasXpackService; import io.dataease.plugins.xpack.display.service.DisplayXpackService; import io.dataease.service.FileService; +import io.dataease.service.datasource.DatasourceService; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -29,7 +29,6 @@ import javax.annotation.Resource; import javax.imageio.ImageIO; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; @@ -47,6 +46,9 @@ public class SystemParameterService { private ExtSystemParameterMapper extSystemParameterMapper; @Resource private FileService fileService; + @Resource + @Lazy + private DatasourceService datasourceService; public String searchEmail() { return extSystemParameterMapper.email(); @@ -86,7 +88,12 @@ public class SystemParameterService { if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_ACCESS_KEY.getValue())) { result.setTemplateAccessKey(param.getParamValue()); } - + if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.DS_CHECK_INTERVAL.getValue())) { + result.setDsCheckInterval(param.getParamValue()); + } + if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.DS_CHECK_INTERVAL_TYPE.getValue())) { + result.setDsCheckIntervalType(param.getParamValue()); + } } } return result; @@ -109,6 +116,7 @@ public class SystemParameterService { @Transactional public CasSaveResult editBasic(List parameters) { CasSaveResult casSaveResult = afterSwitchDefaultLogin(parameters); + BasicInfo basicInfo = basicInfo(); for (int i = 0; i < parameters.size(); i++) { SystemParameter parameter = parameters.get(i); SystemParameterExample example = new SystemParameterExample(); @@ -121,9 +129,11 @@ public class SystemParameterService { } example.clear(); } + datasourceService.updateDatasourceStatusJob(basicInfo, parameters); return casSaveResult; } + @Transactional public void resetCas() { Map beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((CasXpackService.class)); @@ -188,7 +198,6 @@ public class SystemParameterService { } - public String getVersion() { return System.getenv("MS_VERSION"); } @@ -302,10 +311,11 @@ public class SystemParameterService { } } - public BasicInfo templateMarketInfo(){ + + public BasicInfo templateMarketInfo() { BasicInfo basicInfo = new BasicInfo(); List result = this.getParamList("basic.template"); - if(CollectionUtils.isNotEmpty(result)){ + if (CollectionUtils.isNotEmpty(result)) { result.stream().forEach(param -> { if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_MARKET_ULR.getValue())) { basicInfo.setTemplateMarketUlr(param.getParamValue()); @@ -315,7 +325,7 @@ public class SystemParameterService { } }); } - if(StringUtils.isEmpty(basicInfo.getTemplateMarketUlr())|| StringUtils.isEmpty(basicInfo.getTemplateAccessKey())){ + if (StringUtils.isEmpty(basicInfo.getTemplateMarketUlr()) || StringUtils.isEmpty(basicInfo.getTemplateAccessKey())) { DataEaseException.throwException("Please check market setting info"); } return basicInfo; diff --git a/backend/src/main/resources/db/migration/V40__1.15.sql b/backend/src/main/resources/db/migration/V40__1.15.sql index e6b292b6ce..3df26b9c03 100644 --- a/backend/src/main/resources/db/migration/V40__1.15.sql +++ b/backend/src/main/resources/db/migration/V40__1.15.sql @@ -8,3 +8,20 @@ CREATE TABLE `sys_external_token` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; UPDATE `sys_menu` set `component` = 'system/datasource/DsForm' where `component` = 'system/datasource/form'; + + +INSERT INTO `system_parameter`(`param_key`, `param_value`, `type`, `sort`) VALUES ('basic.dsCheckInterval', 20, 'text', 1); +INSERT INTO `system_parameter`(`param_key`, `param_value`, `type`, `sort`) VALUES ('basic.dsCheckIntervalType', 'minute', 'text', 1); + +CREATE TABLE `task_instance` ( + `task_id` VARCHAR(128) NOT NULL COMMENT '任务ID', + `execute_time` bigint(13) DEFAULT NULL COMMENT '执行时间', + `finish_time` bigint(13) DEFAULT NULL COMMENT '完成时间', + `status` VARCHAR(128) DEFAULT NULL COMMENT '状态', + `info` longtext COMMENT '执行信息', + `qrtz_instance` VARCHAR(128) DEFAULT NULL COMMENT '任务实例ID', + PRIMARY KEY (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; + +INSERT INTO `task_instance` (`task_id`) VALUES ('Datasource_check_status'); + diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 525f7fc76d..bba26d4a95 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -794,6 +794,7 @@ export default { no_more_than: 'Size no more than', request_timeout: 'Request timeout', message_retention_time: 'Message retention time', + ds_check_time: 'Data source detection interval', test_mail_recipient: 'Used only as a test mail recipient', to_enable_tsl: 'If the SMTP port is 587, you usually need to enable TSL', to_enable_ssl: 'If the SMTP port is 465, you usually need to enable SSL', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 679796403d..adf4c46c5d 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -794,6 +794,7 @@ export default { no_more_than: '大小不超過', request_timeout: '請求超時時間', message_retention_time: '消息保留時間', + ds_check_time: '数据源檢測時間間隔', test_mail_recipient: '僅用來作為測試郵件收件人', to_enable_tsl: '如果SMTP埠是587,通常需要啟用TSL', to_enable_ssl: '如果SMTP埠是465,通常需要啟用SSL', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 571df4bbf9..4347ac11ec 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -794,6 +794,7 @@ export default { no_more_than: '大小不超过', request_timeout: '请求超时时间', message_retention_time: '消息保留时间', + ds_check_time: '数据源检测时间间隔', test_mail_recipient: '仅用来作为测试邮件收件人', to_enable_tsl: '如果SMTP端口是587,通常需要启用TSL', to_enable_ssl: '如果SMTP端口是465,通常需要启用SSL', diff --git a/frontend/src/views/system/SysParam/BasicSetting.vue b/frontend/src/views/system/SysParam/BasicSetting.vue index 91309eaead..1185d9e152 100644 --- a/frontend/src/views/system/SysParam/BasicSetting.vue +++ b/frontend/src/views/system/SysParam/BasicSetting.vue @@ -31,6 +31,22 @@ slot="append">{{ $t('components.day') }} + + + + + + + + + + + + + + + + {{ @@ -175,6 +191,18 @@ export default { type: "text", sort: 3, }, + { + paramKey: "basic.dsCheckInterval", + paramValue: this.formInline.dsCheckInterval, + type: "text", + sort: 4, + }, + { + paramKey: "basic.dsCheckIntervalType", + paramValue: this.formInline.dsCheckIntervalType, + type: "text", + sort: 5, + }, { paramKey: "ui.openHomePage", paramValue: this.formInline.openHomePage, @@ -234,7 +262,7 @@ export default { window.location.reload(); } else { this.openMessageSuccess("commons.save_failed", 'error'); - } + } }); }, cancel() { @@ -244,6 +272,29 @@ export default { this.show = true; this.query(); }, + onSimpleCronChange() { + if (this.formInline.dsCheckIntervalType === 'minute') { + if (this.formInline.dsCheckInterval < 1 || this.formInline.dsCheckInterval > 59) { + this.$message({ message: this.$t('cron.minute_limit'), type: 'warning', showClose: true }) + this.taskForm.extraData.simple_cron_value = 59 + } + return + } + if (this.formInline.dsCheckIntervalType === 'hour') { + if (this.formInline.dsCheckInterval < 1 || this.formInline.dsCheckInterval > 23) { + this.$message({ message: this.$t('cron.hour_limit'), type: 'warning', showClose: true }) + this.taskForm.extraData.simple_cron_value = 23 + } + return + } + if (this.formInline.dsCheckIntervalType === 'day') { + if (this.formInline.dsCheckInterval < 1 || this.formInline.dsCheckInterval > 31) { + this.$message({ message: this.$t('cron.day_limit'), type: 'warning', showClose: true }) + this.taskForm.extraData.simple_cron_value = 31 + } + return + } + }, }, }; @@ -273,4 +324,4 @@ export default { margin-left: 2px; } } - \ No newline at end of file +