feat: ASW-73 新增 environment 状态检查定时任务

This commit is contained in:
shizhendong
2024-09-18 17:38:59 +08:00
parent 2df576ab10
commit d281ee05d4
4 changed files with 226 additions and 3 deletions

View File

@@ -0,0 +1,83 @@
package net.geedge.asw.common.config.job;
import cn.hutool.log.Log;
import jakarta.annotation.PostConstruct;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.environment.job.JobEnvironmentStatusChecker;
import net.geedge.asw.module.sys.service.ISysConfigService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.util.TimeZone;
@Configuration
public class JobConfig {
private static final Log log = Log.get();
private static final String JOB_NAME_PREFIX = "ASW_JOB";
private static final String JOB_DEFAULT_GROUP = "SYSTEM";
/**
* get job key
* job_name=ASW_JOB_{name}
* group_name=SYSTEM
*/
private static JobKey getJobKey(String name) {
String jobName = T.StrUtil.concat(true, JOB_NAME_PREFIX, "_", name);
return new JobKey(jobName, JOB_DEFAULT_GROUP);
}
@Autowired
private Scheduler scheduler;
@Autowired
private Environment environment;
@Autowired
private ISysConfigService sysConfigService;
@Bean
public JobDetail JobEnvironmentStatusChecker() {
return JobBuilder.newJob(JobEnvironmentStatusChecker.class)
.withIdentity(getJobKey(JobEnvironmentStatusChecker.class.getSimpleName()))
.storeDurably()
.build();
}
@PostConstruct
public void init() throws SchedulerException {
// JobEnvironmentStatusChecker
createCronScheduleJob(JobEnvironmentStatusChecker(), environment.getProperty("asw.cron.JobEnvironmentStatusChecker", "0 0/1 * * * ? *"));
}
/**
* create cron schedule job
* 先删后增
*/
private void createCronScheduleJob(JobDetail jobDetail, String cronExpression) throws SchedulerException {
JobKey key = jobDetail.getKey();
boolean jobExists = scheduler.checkExists(key);
if (log.isDebugEnabled()) {
log.debug("[createCronScheduleJob] [key: {}] [exists: {}]", key.toString(), jobExists);
}
if (jobExists) {
scheduler.deleteJob(key);
log.debug("[createCronScheduleJob] [key: {}] [deleted]", key.toString());
}
String timezone = sysConfigService.getValue("timezone");
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).inTimeZone(TimeZone.getTimeZone(timezone));
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withSchedule(cronScheduleBuilder)
.build();
scheduler.scheduleJob(jobDetail, cronTrigger);
}
}

View File

@@ -0,0 +1,124 @@
package net.geedge.asw.module.environment.job;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import net.geedge.asw.common.util.RCode;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.environment.entity.EnvironmentEntity;
import net.geedge.asw.module.environment.entity.EnvironmentSessionEntity;
import net.geedge.asw.module.environment.service.IEnvironmentService;
import net.geedge.asw.module.environment.service.IEnvironmentSessionService;
import org.apache.commons.lang3.time.StopWatch;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@DisallowConcurrentExecution
public class JobEnvironmentStatusChecker extends QuartzJobBean {
private static final Log log = Log.get();
@Autowired
private IEnvironmentService envService;
@Autowired
private IEnvironmentSessionService envSessionService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
Thread.currentThread().setName("JobEnvironmentStatusChecker");
log.info("[JobEnvironmentStatusChecker] [begin]");
StopWatch sw = new StopWatch();
sw.start();
try {
this.environmentStatusChecker();
} catch (Exception e) {
log.error(e, "[JobEnvironmentStatusChecker] [error]");
} finally {
sw.stop();
}
log.info("[JobEnvironmentStatusChecker] [finshed] [Run Time: {}]", sw.toString());
}
/**
* environment status checker
* <p>
* 1. update entity status、lastHealthCheck
* 2. close the offline env session
*/
@Transactional(rollbackFor = Exception.class)
public void environmentStatusChecker() {
List<EnvironmentEntity> list = envService.list();
for (EnvironmentEntity entity : list) {
Thread.ofVirtual().start(() -> {
String result = null;
try {
JSONObject paramJSONObject = entity.getParamJSONObject();
String url = paramJSONObject.getStr("url");
String token = paramJSONObject.getStr("token");
HttpRequest request = T.HttpUtil.createGet(String.format("%s/api/v1/env/status", url));
request.header("Authorization", token);
HttpResponse response = request.execute();
log.info("[environmentStatusChecker] [env: {}] [status: {}]", entity.getId(), response.getStatus());
if (response.isOk()) {
result = response.body();
}
} catch (RuntimeException e) {
log.error(e, "[environmentStatusChecker] [request api error] [env: {}]", entity.getId());
}
if (log.isDebugEnabled()) {
log.debug("[environmentStatusChecker] [env: {}] [result: {}]", entity.getId(), result);
}
entity.setStatus(0);
entity.setLastHealthCheck(System.currentTimeMillis());
if (T.StrUtil.isNotEmpty(result)) {
try {
JSONObject jsonObject = T.JSONUtil.parseObj(result);
if (T.ObjectUtil.equal(RCode.SUCCESS.getCode(), jsonObject.getInt("code"))) {
JSONObject data = jsonObject.getJSONObject("data");
String status = data.getStr("status");
if (T.StrUtil.equals("online", status)) {
entity.setStatus(1);
}
}
} catch (Exception e) {
log.error(e, "[environmentStatusChecker] [parse result error] [env: {}]", entity.getId());
}
}
// update entity status、lastHealthCheck
envService.update(new LambdaUpdateWrapper<EnvironmentEntity>()
.set(EnvironmentEntity::getStatus, entity.getStatus())
.set(EnvironmentEntity::getLastHealthCheck, entity.getLastHealthCheck())
.eq(EnvironmentEntity::getId, entity.getId())
);
// close the offline env session
if (0 == entity.getStatus()) {
envSessionService.update(new LambdaUpdateWrapper<EnvironmentSessionEntity>()
.set(EnvironmentSessionEntity::getStatus, 2)
.set(EnvironmentSessionEntity::getEndTimestamp, System.currentTimeMillis())
.eq(EnvironmentSessionEntity::getStatus, 1)
.eq(EnvironmentSessionEntity::getEnvId, entity.getId())
);
}
});
}
}
}

View File

@@ -6,4 +6,8 @@ import net.geedge.asw.module.sys.entity.SysConfigEntity;
public interface ISysConfigService extends IService<SysConfigEntity> {
String getValue(String key);
String getValueOrDefault(String key, String defaultValue);
}

View File

@@ -1,14 +1,26 @@
package net.geedge.asw.module.sys.service.impl;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.sys.dao.SysConfigDao;
import net.geedge.asw.module.sys.entity.SysConfigEntity;
import net.geedge.asw.module.sys.service.ISysConfigService;
import org.springframework.stereotype.Service;
@Service
public class SysConfigServiceImpl extends ServiceImpl<SysConfigDao, SysConfigEntity> implements ISysConfigService {
@Override
public String getValue(String key) {
SysConfigEntity config = this.getOne(new LambdaQueryWrapper<SysConfigEntity>().eq(SysConfigEntity::getParamKey, key));
return config == null ? "" : config.getParamValue();
}
@Override
public String getValueOrDefault(String key, String defaultValue) {
String value = this.getValue(key);
return T.StrUtil.isEmpty(value) ? defaultValue : value;
}
}