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.mysql.rule.IotSceneRuleMapper;
|
||||
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.product.IotProductService;
|
||||
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.timer.IotSceneRuleTimerHandler;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -47,9 +47,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
||||
@Resource
|
||||
private IotSceneRuleMapper sceneRuleMapper;
|
||||
|
||||
// TODO @puhui999:定时任务,基于它调度;
|
||||
@Resource(name = "iotSchedulerManager")
|
||||
private IotSchedulerManager schedulerManager;
|
||||
@Resource
|
||||
private IotProductService productService;
|
||||
@Resource
|
||||
@@ -59,11 +56,17 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
||||
private IotSceneRuleMatcherManager sceneRuleMatcherManager;
|
||||
@Resource
|
||||
private List<IotSceneRuleAction> sceneRuleActions;
|
||||
@Resource
|
||||
private IotSceneRuleTimerHandler timerHandler;
|
||||
|
||||
@Override
|
||||
public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
|
||||
IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
|
||||
sceneRuleMapper.insert(sceneRule);
|
||||
|
||||
// 注册定时触发器
|
||||
timerHandler.registerTimerTriggers(sceneRule);
|
||||
|
||||
return sceneRule.getId();
|
||||
}
|
||||
|
||||
@@ -74,6 +77,9 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
||||
// 更新
|
||||
IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class);
|
||||
sceneRuleMapper.updateById(updateObj);
|
||||
|
||||
// 更新定时触发器
|
||||
timerHandler.updateTimerTriggers(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,12 +89,26 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
||||
// 更新状态
|
||||
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
|
||||
sceneRuleMapper.updateById(updateObj);
|
||||
|
||||
// 根据状态管理定时触发器
|
||||
if (CommonStatusEnum.isEnable(status)) {
|
||||
// 启用时,获取完整的场景规则信息并注册定时触发器
|
||||
IotSceneRuleDO sceneRule = sceneRuleMapper.selectById(id);
|
||||
if (sceneRule != null) {
|
||||
timerHandler.registerTimerTriggers(sceneRule);
|
||||
}
|
||||
} else {
|
||||
// 禁用时,暂停定时触发器
|
||||
timerHandler.pauseTimerTriggers(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSceneRule(Long id) {
|
||||
// 校验存在
|
||||
validateSceneRuleExists(id);
|
||||
// 删除定时触发器
|
||||
timerHandler.unregisterTimerTriggers(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