Commit b64120d8 authored by tangwei's avatar tangwei

同步定时任务锁

parent 0bdd5b54
package com.yeejoin.amos.boot.biz.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @description:
* @author: tw
* @createDate: 2022/9/7
*/
@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfigProperties {
private String password;
private cluster cluster;
private String redissonUrl;
private String mode;
public static class cluster {
private List<String> nodes;
public List<String> getNodes() {
return nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public RedisConfigProperties.cluster getCluster() {
return cluster;
}
public void setCluster(RedisConfigProperties.cluster cluster) {
this.cluster = cluster;
}
public String getRedissonUrl() {
return redissonUrl;
}
public void setRedissonUrl(String redissonUrl) {
this.redissonUrl = redissonUrl;
}
public String getMode() {
return mode;
}
public void setMode(String mode) {
this.mode = mode;
}
}
package com.yeejoin.amos.boot.biz.config;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* @description:
* @author: tw
* @createDate: 2022/9/7
*/
@Configuration
public class RedissonConfig {
@Autowired
private RedisConfigProperties redisConfigProperties;
/**
* 集群模式的 redisson 客户端
*
* @return
*/
@Bean
@ConditionalOnProperty(name = "spring.redis.mode", havingValue = "cluster")
public RedissonClient redissonClient() {
//redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
List<String> clusterNodes = new ArrayList<>();
System.out.println("cluster redisProperties:" + redisConfigProperties.getCluster().toString());
for (int i = 0; i < redisConfigProperties.getCluster().getNodes().size(); i++) {
clusterNodes.add("redis://" + redisConfigProperties.getCluster().getNodes().get(i));
}
Config config = new Config();
ClusterServersConfig clusterServersConfig = config.useClusterServers()
.setScanInterval(2000) // 集群状态扫描间隔时间,单位是毫秒
.addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()]));
// 设置密码
if (StringUtils.isNotBlank(redisConfigProperties.getPassword())) {
clusterServersConfig.setPassword(redisConfigProperties.getPassword());
}
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
/**
* 单机模式 redisson 客户端
*/
@Bean
@ConditionalOnProperty(name = "spring.redis.mode", havingValue = "single")
RedissonClient redissonSingle() {
Config config = new Config();
String node = redisConfigProperties.getRedissonUrl();
node = node.startsWith("redis://") ? node : "redis://" + node;
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(node);
if (StringUtils.isNotBlank(redisConfigProperties.getPassword())) {
serverConfig.setPassword(redisConfigProperties.getPassword());
}
return Redisson.create(config);
}
}
\ No newline at end of file
package com.yeejoin.equipmanage.quartz;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.equipmanage.common.enums.AnalysisReportEnum;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.service.IAnalysisReportLogService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @author DELL
......@@ -20,15 +25,43 @@ public class AnalysisReportSchedulerJob {
@Autowired
private IAnalysisReportLogService iAnalysisReportLogService;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
/**
* 每天凌晨0点-日报生成
*/
@Scheduled(cron = "0 0 0 * * ?")
public void dayReport() throws ParseException {
Date beginDate = DateUtils.dateAdd(new Date(),-1,false);
Date endDate = DateUtils.dateAdd(new Date(),-1,false);
iAnalysisReportLogService.generateReport(AnalysisReportEnum.DAY_REPORT,beginDate,endDate);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "dayReport" + time;
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_dayReport_key")) {
redisUtils.set(jobName + "_dayReport_key", "1");//增加标识
Date beginDate = DateUtils.dateAdd(new Date(), -1, false);
Date endDate = DateUtils.dateAdd(new Date(), -1, false);
iAnalysisReportLogService.generateReport(AnalysisReportEnum.DAY_REPORT, beginDate, endDate);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
/**
......@@ -36,10 +69,30 @@ public class AnalysisReportSchedulerJob {
*/
@Scheduled(cron = "0 0 0 ? * 1")
public void weekReport() throws ParseException {
Date yestDay = DateUtils.dateAdd(new Date(),-1,false);
Date beginDate = DateUtils.getFirstDayOfWeek(yestDay);
Date endDate = DateUtils.getLastDayOfWeek(yestDay);
iAnalysisReportLogService.generateReport(AnalysisReportEnum.WEEK_REPORT,beginDate,endDate);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "weekReport" + time;
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_weekReport_key")) {
redisUtils.set(jobName + "_weekReport_key", "1");//增加标识
Date yestDay = DateUtils.dateAdd(new Date(), -1, false);
Date beginDate = DateUtils.getFirstDayOfWeek(yestDay);
Date endDate = DateUtils.getLastDayOfWeek(yestDay);
iAnalysisReportLogService.generateReport(AnalysisReportEnum.WEEK_REPORT, beginDate, endDate);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
/**
......@@ -47,9 +100,28 @@ public class AnalysisReportSchedulerJob {
*/
@Scheduled(cron="0 0 0 1 * ?")
public void monthReport() throws ParseException {
Date yestDay = DateUtils.dateAdd(new Date(),-1,false);
Date beginDate = DateUtils.getFirstDayOfMonth(yestDay);
Date endDate = DateUtils.getLastDayOfMonth(yestDay);
iAnalysisReportLogService.generateMonthReport(AnalysisReportEnum.MONTH_REPORT,beginDate,endDate);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "monthReport" + time;
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_monthReport_key")) {
redisUtils.set(jobName + "_monthReport_key", "1");//增加标识
Date yestDay = DateUtils.dateAdd(new Date(), -1, false);
Date beginDate = DateUtils.getFirstDayOfMonth(yestDay);
Date endDate = DateUtils.getLastDayOfMonth(yestDay);
iAnalysisReportLogService.generateMonthReport(AnalysisReportEnum.MONTH_REPORT, beginDate, endDate);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
......@@ -5,8 +5,13 @@ import static com.yeejoin.amos.fas.business.constants.FasConstant.product;
import static com.yeejoin.amos.fas.business.constants.FasConstant.staticOrgCode;
import static com.yeejoin.amos.fas.business.constants.FasConstant.token;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
......@@ -17,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.fas.business.bo.BindPointBo;
......@@ -43,7 +49,10 @@ public class View3dController extends AbstractBaseController {
private IRiskSourceService riskSourceService;
@Autowired
private IView3dService view3dService;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(httpMethod = "POST", value = "点3d坐标设置", notes = "按照点类型3d坐标设置" )
@PostMapping(value = "/point/bind",produces = "application/json;charset=UTF-8")
......@@ -218,7 +227,31 @@ public class View3dController extends AbstractBaseController {
@Scheduled(cron = "${param.safetyIndexChange.cron}")
public CommonResponse safetyIndexLog(){
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "fas-2" + time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
view3dService.safetyIndexLogGenJob(null);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
return CommonResponseUtil.success();
}
......
package com.yeejoin.amos.fas.business.scheduled;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -18,34 +24,61 @@ public class FireScheduled {
private static LinkedList<Map<String, String>> fireQueue = new LinkedList<>();
@Autowired
IContingencyInstance iContingencyInstance;
@Autowired
RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Scheduled(cron = "*/2 * * * * ?")
public void runFireQueue() throws Exception {
if (fireQueue.size() == 0)
return;
Map<String, String> map = fireQueue.getFirst();
String batchNo = map.get("batchNo");
String stepCode = map.get("stepCode");
String buttonCode = map.get("buttonCode");
String confirm = map.get("confirm");
String contingencyPlanId = map.get("contingencyPlanId");
String stepState = map.get("stepState");
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "fas-1" + time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
if (fireQueue.size() == 0)
return;
Map<String, String> map = fireQueue.getFirst();
String batchNo = map.get("batchNo");
String stepCode = map.get("stepCode");
String buttonCode = map.get("buttonCode");
String confirm = map.get("confirm");
String contingencyPlanId = map.get("contingencyPlanId");
String stepState = map.get("stepState");
// String token = map.get("token");
// String product = map.get("product");
try {
log.info("fireQueue-size:" + fireQueue.size());
log.info("stepCode:" + map.get("stepCode"));
log.info("buttonCode:" + map.get("buttonCode"));
log.info("confirm:" + map.get("confirm"));
log.info("stepState:" + map.get("stepState"));
log.info("fireQueue-size:" + fireQueue.size());
log.info("stepCode:" + map.get("stepCode"));
log.info("buttonCode:" + map.get("buttonCode"));
log.info("confirm:" + map.get("confirm"));
log.info("stepState:" + map.get("stepState"));
// RequestContext.setToken(token);
// RequestContext.setProduct(product);
iContingencyInstance.setButtonExecuted(batchNo, contingencyPlanId, buttonCode, confirm);
iContingencyInstance.fire(batchNo, stepCode, contingencyPlanId, buttonCode, confirm, stepState);
iContingencyInstance.setButtonExecuted(batchNo, contingencyPlanId, buttonCode, confirm);
iContingencyInstance.fire(batchNo, stepCode, contingencyPlanId, buttonCode, confirm, stepState);
}
} catch (Exception e) {
throw e;
} finally {
fireQueue.removeFirst();
lock.unlock(); //释放锁
}
}
public static LinkedList<Map<String, String>> getFireQueue() {
......
package com.yeejoin.amos.knowledgebase.face.util;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeInteractionCount;
import com.yeejoin.amos.knowledgebase.face.service.DocAuditService;
import com.yeejoin.amos.knowledgebase.face.service.InteractionCountService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
......@@ -30,6 +37,12 @@ public class QuoteCountFlushTiming {
@Autowired
private ConfigLoader configLoader;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
public static void needFlushTag() {
needFlush.set(true);
}
......@@ -41,7 +54,22 @@ public class QuoteCountFlushTiming {
@Scheduled(fixedRate = 5 * 1000)
@Transactional(rollbackFor = {Exception.class, BaseException.class})
public void flushTagQuoteCount() {
if (needFlush.get()) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "knowledgeBase-1" +time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
if (needFlush.get()) {
needFlush.set(false);
interactionCountService.deleteAllTagQuote();
List<KnowledgeInteractionCount> allTagQuoteRecords = interactionCountService.getAllTagQuoteRecords();
......@@ -51,16 +79,46 @@ public class QuoteCountFlushTiming {
System.out.println("定时-刷新标签引用数-" + (finished ? "完成" : "失败"));
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
@Scheduled(fixedRate = 3 * 1000)
@Transactional(rollbackFor = {Exception.class, BaseException.class})
public void pushDocs2Rule() {
if (needPush2Rule.get()) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "knowledgeBase-2" + time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
if (needPush2Rule.get()) {
needPush2Rule.set(false);
docAuditService.pushDocs2RuleByMQ();
System.out.println("定时-同步规则-完成");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
package com.yeejoin.amos.maintenance.quartz;
import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.MessageModel;
import com.yeejoin.amos.maintenance.business.constants.XJConstant;
......@@ -19,6 +20,7 @@ import com.yeejoin.amos.maintenance.dao.entity.*;
import com.yeejoin.amos.maintenance.feign.RemoteSecurityService;
import com.yeejoin.amos.maintenance.mqtt.MqttGateway;
import org.quartz.Job;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -26,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import java.util.concurrent.TimeUnit;
import java.text.ParseException;
import java.text.SimpleDateFormat;
......@@ -73,6 +76,13 @@ public class JobService implements IJobService {
@Value("${amosRefresh.patrol.topic}")
private String patrolTopic;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Override
@Transactional
public void initScheduler() {
......@@ -293,7 +303,17 @@ public class JobService implements IJobService {
@Override
@Transactional
public void taskJobPerform(long taskId, String jobType, String jobName) {
if (iTaskDao.existsById(taskId)) {
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iTaskDao.existsById(taskId)) {
Task task = iTaskDao.findById(taskId).get();
Toke toke = remoteSecurityService.getServerToken();
if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
......@@ -323,6 +343,13 @@ public class JobService implements IJobService {
}
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
@Override
......@@ -379,12 +406,28 @@ public class JobService implements IJobService {
@Override
public void msgJobPerform(long msgId, String jobType, String jobName) {
if (iMsgDao.existsById(msgId)) {
Msg msg = iMsgDao.findById(msgId).get();
Toke toke = remoteSecurityService.getServerToken();
messageService.pushMsg(toke.getToke(), toke.getProduct(), toke.getAppKey(), msg);
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iMsgDao.existsById(msgId)) {
Msg msg = iMsgDao.findById(msgId).get();
Toke toke = remoteSecurityService.getServerToken();
messageService.pushMsg(toke.getToke(), toke.getProduct(), toke.getAppKey(), msg);
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
removeJob(jobName);
}
}
package com.yeejoin.amos.maintenance.task;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.maintenance.business.service.intfc.IPlanTaskService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @author DELL
*/
......@@ -13,6 +20,10 @@ import org.springframework.stereotype.Component;
@EnableScheduling
public class PlanTaskJob {
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Autowired
private IPlanTaskService planTaskService;
......@@ -22,7 +33,31 @@ public class PlanTaskJob {
*/
@Scheduled(cron = "${jobs.cron}")
public void scheduleJob() {
planTaskService.taskExecution(null);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "maintenance-1" + time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
planTaskService.taskExecution(null);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
/**
......@@ -30,6 +65,28 @@ public class PlanTaskJob {
*/
@Scheduled(cron = "${jobs.cron}")
public void taskMessage() {
planTaskService.taskMessage(null);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "maintenance-2" + time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
planTaskService.taskMessage(null);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
......@@ -2,6 +2,7 @@ package com.yeejoin.amos.patrol.business.controller;
import com.alibaba.fastjson.JSONObject;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.patrol.business.constants.XJConstant;
import com.yeejoin.amos.patrol.business.param.PlanTaskPageParam;
......@@ -25,6 +26,7 @@ import com.yeejoin.amos.patrol.feign.RemoteSecurityService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -37,6 +39,9 @@ import org.springframework.web.context.request.RequestContextHolder;
import org.typroject.tyboot.core.foundation.enumeration.UserType;
import org.typroject.tyboot.core.restful.doc.TycloudOperation;
import java.text.DateFormat;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
......@@ -66,7 +71,11 @@ public class PlanTaskController extends AbstractBaseController {
/* @Autowired
private IUserService userService;*/
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@TycloudOperation(ApiLevel = UserType.AGENCY)
@ApiOperation(value = "计划执行查询", notes = "计划执行查询")
......@@ -389,16 +398,36 @@ public class PlanTaskController extends AbstractBaseController {
@ApiOperation(value = "定时执行任务表生成(<font color='blue'>release</font>)", notes = "定时执行任务表生成")
@RequestMapping(value = "/queryOmission", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public CommonResponse pushCarData() {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "pushCarData" +time;
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
RequestAttributes reqs = RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(reqs, true);
planTaskService.taskExecution(null);
return CommonResponseUtil.success();
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_pushCarData_key")) {
redisUtils.set(jobName + "_pushCarData_key", "1");//增加标识
RequestAttributes reqs = RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(reqs, true);
planTaskService.taskExecution(null);
}
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
return CommonResponseUtil.failure();
}finally {
lock.unlock(); //释放锁
}
return CommonResponseUtil.success();
}
/**
......@@ -406,9 +435,26 @@ public class PlanTaskController extends AbstractBaseController {
*/
@Scheduled(cron = "${jobs.cron}")
public void taskMessage() {
RequestAttributes reqs = RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(reqs, true);
planTaskService.taskMessage(null);
String jobName = "taskMessage" + System.currentTimeMillis();
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_taskMessage_key")) {
redisUtils.set(jobName + "_taskMessage_key", "1");//增加标识
RequestAttributes reqs = RequestContextHolder.getRequestAttributes();
RequestContextHolder.setRequestAttributes(reqs, true);
planTaskService.taskMessage(null);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
/**
......
......@@ -89,7 +89,7 @@ public class UserController extends AbstractBaseController {
private String SecurityName;
@Value("${security.productApp}")
private String productApp;
@Value("${security.appKey}")
@Value("${amos.system.user.app-key}")
private String appKey;
@Autowired
private RestTemplate restTemplate;
......
package com.yeejoin.amos.patrol.quartz;
import com.alibaba.fastjson.JSON;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
......@@ -25,6 +26,7 @@ import com.yeejoin.amos.patrol.feign.RemoteSecurityService;
import com.yeejoin.amos.patrol.mqtt.WebMqttComponent;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.Job;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -33,7 +35,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import java.util.concurrent.TimeUnit;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
......@@ -94,6 +96,10 @@ public class JobService implements IJobService {
@Autowired
JcsFeignClient jcsFeignClient;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Override
......@@ -653,41 +659,56 @@ public class JobService implements IJobService {
@Transactional
public void taskJobPerform(long taskId, String jobType, String jobName) {
// TODO Auto-generated method stub
if (iTaskDao.existsById(taskId)) {
Task task = iTaskDao.findById(taskId).get();
Toke toke= remoteSecurityService.getServerToken();
if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
if (TaskStatusEnum.UNDERWAY.getValue() == task.getStatus()) {
task.setStatus(TaskStatusEnum.OVERTIME.getValue());
iTaskDao.saveAndFlush(task);
TaskFeedback taskFeedback = new TaskFeedback();
taskFeedback.setUserId(task.getExecutorId());
taskFeedback.setMessage("该任务在规定时间内未完成,请核实信息!任务名称: " + task.getTitle() + " 要求完成时间: "
+ DateUtil.getDateFormat(task.getFinishTime(), "yyyy-MM-dd HH:mm:ss") + " 发起人:"
+ task.getPublisherName() + " 执行人:" + task.getExecutor());
taskFeedback.setCreateDate(new Date());
taskFeedback.setUserName(task.getExecutor());
taskFeedback.setFeedbackTime(new Date());
taskFeedback.setOrgCode(task.getOrgCode());
taskFeedback.setTaskId(task.getId());
taskFeedback.setMessageType(TaskStatusEnum.OVERTIME.getName());
taskFeedback = taskFeedbackDao.save(taskFeedback);
try {
asyncTask.pushTaskDetailInfoTo3D(toke.getToke(), toke.getProduct(), toke.getAppKey(),taskId); // 超时任务向3D推送
} catch (InterruptedException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
e.printStackTrace();
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if(!redisUtils.hasKey(jobName+"_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iTaskDao.existsById(taskId)) {
Task task = iTaskDao.findById(taskId).get();
Toke toke = remoteSecurityService.getServerToken();
if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
if (TaskStatusEnum.UNDERWAY.getValue() == task.getStatus()) {
task.setStatus(TaskStatusEnum.OVERTIME.getValue());
iTaskDao.saveAndFlush(task);
TaskFeedback taskFeedback = new TaskFeedback();
taskFeedback.setUserId(task.getExecutorId());
taskFeedback.setMessage("该任务在规定时间内未完成,请核实信息!任务名称: " + task.getTitle() + " 要求完成时间: "
+ DateUtil.getDateFormat(task.getFinishTime(), "yyyy-MM-dd HH:mm:ss") + " 发起人:"
+ task.getPublisherName() + " 执行人:" + task.getExecutor());
taskFeedback.setCreateDate(new Date());
taskFeedback.setUserName(task.getExecutor());
taskFeedback.setFeedbackTime(new Date());
taskFeedback.setOrgCode(task.getOrgCode());
taskFeedback.setTaskId(task.getId());
taskFeedback.setMessageType(TaskStatusEnum.OVERTIME.getName());
taskFeedback = taskFeedbackDao.save(taskFeedback);
try {
asyncTask.pushTaskDetailInfoTo3D(toke.getToke(), toke.getProduct(), toke.getAppKey(), taskId); // 超时任务向3D推送
} catch (InterruptedException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
e.printStackTrace();
}
}
} else {
messageService.pushTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(), task);
}
}
} else {
messageService.pushTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(),task);
removeJob(jobName);
}
}
removeJob(jobName);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
@Override
public void planTaskAddJob(PlanTask planTask) {
......@@ -744,6 +765,13 @@ public class JobService implements IJobService {
@Override
@Transactional
public void planTaskJobPerform(long planTaskId, String jobType, String jobName) {
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
if(!redisUtils.hasKey(jobName+"_redisson_key")){
redisUtils.set(jobName+"_redisson_key","1");//增加标识
if (iPlanTaskDao.existsById(planTaskId)) {
PlanTask planTask = iPlanTaskDao.findById(planTaskId).get();
......@@ -762,6 +790,13 @@ public class JobService implements IJobService {
}
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
@Override
......@@ -771,12 +806,27 @@ public class JobService implements IJobService {
@Override
public void msgJobPerform(long msgId, String jobType, String jobName) {
if (iMsgDao.existsById(msgId)) {
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if(!redisUtils.hasKey(jobName+"_redisson_key")){
redisUtils.set(jobName+"_redisson_key","1");//增加标识
if (iMsgDao.existsById(msgId)) {
Msg msg = iMsgDao.findById(msgId).get();
Toke toke= remoteSecurityService.getServerToken();
messageService.pushMsgAndSave(toke.getToke(), toke.getProduct(), toke.getAppKey(),msg);
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
package com.yeejoin.amos.patrol.schedule;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.patrol.business.service.intfc.ILatentDangerService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* 隐患定时任务
*/
......@@ -14,6 +21,11 @@ public class LatentDanerScheduled {
@Autowired
private ILatentDangerService iLatentDangerService;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
/**
* 每1分钟执行一次:查询逾期的隐患,修改状态
......@@ -21,6 +33,31 @@ public class LatentDanerScheduled {
@Scheduled(cron = "0 0/1 * * * ?")
public void updateDangerStateOfOvertime() {
iLatentDangerService.updateDangerStateOfOvertime();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "updateDangerStateOfOvertime" +time;
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_updateDangerStateOfOvertime_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
iLatentDangerService.updateDangerStateOfOvertime();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
\ No newline at end of file
package com.yeejoin.amos.supervision.quartz;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.supervision.business.constants.XJConstant;
import com.yeejoin.amos.supervision.business.dao.mapper.CheckMapper;
import com.yeejoin.amos.supervision.business.dao.mapper.MsgMapper;
......@@ -37,6 +38,7 @@ import com.yeejoin.amos.supervision.dao.entity.PlanTaskDetail;
import com.yeejoin.amos.supervision.dao.entity.Task;
import com.yeejoin.amos.supervision.dao.entity.TaskFeedback;
import org.quartz.Job;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -44,6 +46,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import java.util.concurrent.TimeUnit;
import java.text.ParseException;
import java.text.SimpleDateFormat;
......@@ -100,6 +103,11 @@ public class JobService implements IJobService {
private String patrolTopic;
@Autowired
private WebMqttComponent webMqttComponent;
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Override
@Transactional
......@@ -220,7 +228,7 @@ public class JobService implements IJobService {
List<Check> checkList = checkMapper.getCheckListByTaskId(planTask.getId());
Map<Long, Check> checkMap = new HashMap<>();
if (!ValidationUtil.isEmpty(checkList)) {
checkList.stream().collect(Collectors.groupingBy(Check::getPointId)).forEach((e,v) -> {
checkList.stream().collect(Collectors.groupingBy(Check::getPointId)).forEach((e, v) -> {
checkMap.put(e, v.get(0));
});
}
......@@ -296,37 +304,53 @@ public class JobService implements IJobService {
@Override
@Transactional
public void taskJobPerform(long taskId, String jobType, String jobName) {
if (iTaskDao.existsById(taskId)) {
Task task = iTaskDao.findById(taskId).get();
Toke toke = remoteSecurityService.getServerToken();
if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
if (TaskStatusEnum.UNDERWAY.getValue() == task.getStatus()) {
task.setStatus(TaskStatusEnum.OVERTIME.getValue());
iTaskDao.saveAndFlush(task);
TaskFeedback taskFeedback = new TaskFeedback();
taskFeedback.setUserId(task.getExecutorId());
taskFeedback.setMessage("该任务在规定时间内未完成,请核实信息!任务名称: " + task.getTitle() + " 要求完成时间: "
+ DateUtil.getDateFormat(task.getFinishTime(), "yyyy-MM-dd HH:mm:ss") + " 发起人:"
+ task.getPublisherName() + " 执行人:" + task.getExecutor());
taskFeedback.setCreateDate(new Date());
taskFeedback.setUserName(task.getExecutor());
taskFeedback.setFeedbackTime(new Date());
taskFeedback.setOrgCode(task.getOrgCode());
taskFeedback.setTaskId(task.getId());
taskFeedback.setMessageType(TaskStatusEnum.OVERTIME.getName());
taskFeedback = taskFeedbackDao.save(taskFeedback);
try {
asyncTask.pushTaskDetailInfoTo3D(toke.getToke(), toke.getProduct(), toke.getAppKey(), taskId); // 超时任务向3D推送
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName + "_redisson");
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iTaskDao.existsById(taskId)) {
Task task = iTaskDao.findById(taskId).get();
Toke toke = remoteSecurityService.getServerToken();
if (XJConstant.STATUS_MONITOR_END.equals(jobType)) {
if (TaskStatusEnum.UNDERWAY.getValue() == task.getStatus()) {
task.setStatus(TaskStatusEnum.OVERTIME.getValue());
iTaskDao.saveAndFlush(task);
TaskFeedback taskFeedback = new TaskFeedback();
taskFeedback.setUserId(task.getExecutorId());
taskFeedback.setMessage("该任务在规定时间内未完成,请核实信息!任务名称: " + task.getTitle() + " 要求完成时间: "
+ DateUtil.getDateFormat(task.getFinishTime(), "yyyy-MM-dd HH:mm:ss") + " 发起人:"
+ task.getPublisherName() + " 执行人:" + task.getExecutor());
taskFeedback.setCreateDate(new Date());
taskFeedback.setUserName(task.getExecutor());
taskFeedback.setFeedbackTime(new Date());
taskFeedback.setOrgCode(task.getOrgCode());
taskFeedback.setTaskId(task.getId());
taskFeedback.setMessageType(TaskStatusEnum.OVERTIME.getName());
taskFeedback = taskFeedbackDao.save(taskFeedback);
try {
asyncTask.pushTaskDetailInfoTo3D(toke.getToke(), toke.getProduct(), toke.getAppKey(), taskId); // 超时任务向3D推送
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
}
}
} else {
messageService.pushTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(), task);
}
}
} else {
messageService.pushTaskMessage(toke.getToke(), toke.getProduct(), toke.getAppKey(), task);
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
removeJob(jobName);
}
}
@Override
public void planTaskAddJob(PlanTask planTask) {
......@@ -381,6 +405,17 @@ public class JobService implements IJobService {
@Override
@Transactional
public void planTaskJobPerform(long planTaskId, String jobType, String jobName) {
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName + "_redisson");
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iPlanTaskDao.existsById(planTaskId)) {
PlanTask planTask = iPlanTaskDao.findById(planTaskId).get();
......@@ -400,6 +435,13 @@ public class JobService implements IJobService {
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
@Override
public void msgAddJob(Msg msg) {
......@@ -408,12 +450,27 @@ public class JobService implements IJobService {
@Override
public void msgJobPerform(long msgId, String jobType, String jobName) {
if (iMsgDao.existsById(msgId)) {
//为了便于区分key,增加后缀_redisson
RLock lock = redisson.getLock(jobName + "_redisson");
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//增加标识
if (iMsgDao.existsById(msgId)) {
Msg msg = iMsgDao.findById(msgId).get();
Toke toke = remoteSecurityService.getServerToken();
messageService.pushMsg(toke.getToke(), toke.getProduct(), toke.getAppKey(), msg);
}
removeJob(jobName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
package com.yeejoin.amos.supervision.task;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.supervision.business.service.intfc.IPlanTaskService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @author DELL
*/
......@@ -13,6 +20,10 @@ import org.springframework.stereotype.Component;
@EnableScheduling
public class PlanTaskJob {
@Autowired
org.redisson.api.RedissonClient redisson;
@Autowired
private RedisUtils redisUtils;
@Autowired
private IPlanTaskService planTaskService;
......@@ -22,6 +33,28 @@ public class PlanTaskJob {
*/
@Scheduled(cron = "${jobs.cron}")
public void scheduleJob() {
planTaskService.taskExecution(null);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String time=format.format(new Date());
String jobName = "supervision-1" +time;
RLock lock = redisson.getLock(jobName);
try {
//拿锁失败10停止尝试, 任务执行超时默认续30s 每个10秒续到30
lock.tryLock(10, TimeUnit.SECONDS);
System.out.println("获取锁成功============");
//为了防止重复
if (!redisUtils.hasKey(jobName + "_redisson_key")) {
redisUtils.set(jobName + "_redisson_key", "1");//
planTaskService.taskExecution(null);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock(); //释放锁
}
}
}
......@@ -72,6 +72,14 @@
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.8.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment