feat: 【IoT 物联网】实现场景规则定时触发器的注册,新增定时触发器处理器,支持场景规则的定时任务注册、更新、删除等生命周期管理
This commit is contained in:
@@ -17,11 +17,11 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
|||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
|
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
|
|
||||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||||
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotSceneRuleAction;
|
import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotSceneRuleAction;
|
||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherManager;
|
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherManager;
|
||||||
|
import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -47,9 +47,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
@Resource
|
@Resource
|
||||||
private IotSceneRuleMapper sceneRuleMapper;
|
private IotSceneRuleMapper sceneRuleMapper;
|
||||||
|
|
||||||
// TODO @puhui999:定时任务,基于它调度;
|
|
||||||
@Resource(name = "iotSchedulerManager")
|
|
||||||
private IotSchedulerManager schedulerManager;
|
|
||||||
@Resource
|
@Resource
|
||||||
private IotProductService productService;
|
private IotProductService productService;
|
||||||
@Resource
|
@Resource
|
||||||
@@ -59,11 +56,17 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
private IotSceneRuleMatcherManager sceneRuleMatcherManager;
|
private IotSceneRuleMatcherManager sceneRuleMatcherManager;
|
||||||
@Resource
|
@Resource
|
||||||
private List<IotSceneRuleAction> sceneRuleActions;
|
private List<IotSceneRuleAction> sceneRuleActions;
|
||||||
|
@Resource
|
||||||
|
private IotSceneRuleTimerHandler timerHandler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
|
public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
|
||||||
IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
|
IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
|
||||||
sceneRuleMapper.insert(sceneRule);
|
sceneRuleMapper.insert(sceneRule);
|
||||||
|
|
||||||
|
// 注册定时触发器
|
||||||
|
timerHandler.registerTimerTriggers(sceneRule);
|
||||||
|
|
||||||
return sceneRule.getId();
|
return sceneRule.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +77,9 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
// 更新
|
// 更新
|
||||||
IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class);
|
IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class);
|
||||||
sceneRuleMapper.updateById(updateObj);
|
sceneRuleMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
// 更新定时触发器
|
||||||
|
timerHandler.updateTimerTriggers(updateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -83,12 +89,26 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
// 更新状态
|
// 更新状态
|
||||||
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
|
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
|
||||||
sceneRuleMapper.updateById(updateObj);
|
sceneRuleMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
// 根据状态管理定时触发器
|
||||||
|
if (CommonStatusEnum.isEnable(status)) {
|
||||||
|
// 启用时,获取完整的场景规则信息并注册定时触发器
|
||||||
|
IotSceneRuleDO sceneRule = sceneRuleMapper.selectById(id);
|
||||||
|
if (sceneRule != null) {
|
||||||
|
timerHandler.registerTimerTriggers(sceneRule);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 禁用时,暂停定时触发器
|
||||||
|
timerHandler.pauseTimerTriggers(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteSceneRule(Long id) {
|
public void deleteSceneRule(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
validateSceneRuleExists(id);
|
validateSceneRuleExists(id);
|
||||||
|
// 删除定时触发器
|
||||||
|
timerHandler.unregisterTimerTriggers(id);
|
||||||
// 删除
|
// 删除
|
||||||
sceneRuleMapper.deleteById(id);
|
sceneRuleMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.rule.scene.timer;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
|
||||||
|
import cn.iocoder.yudao.module.iot.job.rule.IotSceneRuleJob;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.SchedulerException;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 场景规则定时触发器处理器
|
||||||
|
* <p>
|
||||||
|
* 负责管理定时触发器的注册、更新、删除等操作
|
||||||
|
*
|
||||||
|
* @author HUIHUI
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class IotSceneRuleTimerHandler {
|
||||||
|
|
||||||
|
@Resource(name = "iotSchedulerManager")
|
||||||
|
private IotSchedulerManager schedulerManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册场景规则的定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRule 场景规则
|
||||||
|
*/
|
||||||
|
public void registerTimerTriggers(IotSceneRuleDO sceneRule) {
|
||||||
|
if (sceneRule == null || CollUtil.isEmpty(sceneRule.getTriggers())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤出定时触发器
|
||||||
|
List<IotSceneRuleDO.Trigger> timerTriggers = filterList(sceneRule.getTriggers(),
|
||||||
|
trigger -> ObjUtil.equals(trigger.getType(), IotSceneRuleTriggerTypeEnum.TIMER.getType()));
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(timerTriggers)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册每个定时触发器
|
||||||
|
timerTriggers.forEach(trigger -> registerSingleTimerTrigger(sceneRule, trigger));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新场景规则的定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRule 场景规则
|
||||||
|
*/
|
||||||
|
public void updateTimerTriggers(IotSceneRuleDO sceneRule) {
|
||||||
|
if (sceneRule == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先删除旧的定时任务
|
||||||
|
unregisterTimerTriggers(sceneRule.getId());
|
||||||
|
|
||||||
|
// 如果场景规则已禁用,则不重新注册
|
||||||
|
if (CommonStatusEnum.isDisable(sceneRule.getStatus())) {
|
||||||
|
log.info("[updateTimerTriggers][场景规则({}) 已禁用,不注册定时触发器]", sceneRule.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新注册定时触发器
|
||||||
|
registerTimerTriggers(sceneRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注销场景规则的定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRuleId 场景规则ID
|
||||||
|
*/
|
||||||
|
public void unregisterTimerTriggers(Long sceneRuleId) {
|
||||||
|
if (sceneRuleId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String jobName = buildJobName(sceneRuleId);
|
||||||
|
try {
|
||||||
|
schedulerManager.deleteJob(jobName);
|
||||||
|
log.info("[unregisterTimerTriggers][场景规则({}) 定时触发器注销成功]", sceneRuleId);
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.error("[unregisterTimerTriggers][场景规则({}) 定时触发器注销失败]", sceneRuleId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 暂停场景规则的定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRuleId 场景规则ID
|
||||||
|
*/
|
||||||
|
public void pauseTimerTriggers(Long sceneRuleId) {
|
||||||
|
if (sceneRuleId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String jobName = buildJobName(sceneRuleId);
|
||||||
|
try {
|
||||||
|
schedulerManager.pauseJob(jobName);
|
||||||
|
log.info("[pauseTimerTriggers][场景规则({}) 定时触发器暂停成功]", sceneRuleId);
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.error("[pauseTimerTriggers][场景规则({}) 定时触发器暂停失败]", sceneRuleId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复场景规则的定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRuleId 场景规则ID
|
||||||
|
*/
|
||||||
|
public void resumeTimerTriggers(Long sceneRuleId) {
|
||||||
|
if (sceneRuleId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String jobName = buildJobName(sceneRuleId);
|
||||||
|
try {
|
||||||
|
schedulerManager.resumeJob(jobName);
|
||||||
|
log.info("[resumeTimerTriggers][场景规则({}) 定时触发器恢复成功]", sceneRuleId);
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.error("[resumeTimerTriggers][场景规则({}) 定时触发器恢复失败]", sceneRuleId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册单个定时触发器
|
||||||
|
*
|
||||||
|
* @param sceneRule 场景规则
|
||||||
|
* @param trigger 定时触发器配置
|
||||||
|
*/
|
||||||
|
private void registerSingleTimerTrigger(IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) {
|
||||||
|
// 1. 参数校验
|
||||||
|
if (StrUtil.isBlank(trigger.getCronExpression())) {
|
||||||
|
log.error("[registerSingleTimerTrigger][场景规则({}) 定时触发器缺少 CRON 表达式]", sceneRule.getId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 构建任务名称和数据
|
||||||
|
String jobName = buildJobName(sceneRule.getId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 3. 注册定时任务
|
||||||
|
schedulerManager.addOrUpdateJob(
|
||||||
|
IotSceneRuleJob.class,
|
||||||
|
jobName,
|
||||||
|
trigger.getCronExpression(),
|
||||||
|
IotSceneRuleJob.buildJobDataMap(sceneRule.getId())
|
||||||
|
);
|
||||||
|
|
||||||
|
log.info("[registerSingleTimerTrigger][场景规则({}) 定时触发器注册成功,CRON: {}]",
|
||||||
|
sceneRule.getId(), trigger.getCronExpression());
|
||||||
|
} catch (SchedulerException e) {
|
||||||
|
log.error("[registerSingleTimerTrigger][场景规则({}) 定时触发器注册失败,CRON: {}]",
|
||||||
|
sceneRule.getId(), trigger.getCronExpression(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建任务名称
|
||||||
|
*
|
||||||
|
* @param sceneRuleId 场景规则ID
|
||||||
|
* @return 任务名称
|
||||||
|
*/
|
||||||
|
private String buildJobName(Long sceneRuleId) {
|
||||||
|
return "iot_scene_rule_timer_" + sceneRuleId;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user