Commit 997bfe8fa116c0f2bb0c4149d08d95bd37e52ab6
1 parent
057f924b
feat: 【IoT 物联网】场景联动规则的数据缓存,使用 Spring Cache 操作
Showing
3 changed files
with
24 additions
and
11 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
| @@ -76,4 +76,12 @@ public interface RedisKeyConstants { | @@ -76,4 +76,12 @@ public interface RedisKeyConstants { | ||
| 76 | */ | 76 | */ |
| 77 | String DATA_SINK = "iot:data_sink"; | 77 | String DATA_SINK = "iot:data_sink"; |
| 78 | 78 | ||
| 79 | + /** | ||
| 80 | + * 场景联动规则的数据缓存,使用 Spring Cache 操作 | ||
| 81 | + * <p> | ||
| 82 | + * KEY 格式:scene_rule_list_${productId}_${deviceId} | ||
| 83 | + * VALUE 数据类型:String 数组(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO} 列表 | ||
| 84 | + */ | ||
| 85 | + String SCENE_RULE_LIST = "iot:scene_rule_list"; | ||
| 86 | + | ||
| 79 | } | 87 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotSceneRuleServiceImpl.java
| @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | ||
| 16 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | 16 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 17 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; | 17 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 18 | import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper; | 18 | import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper; |
| 19 | +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | ||
| 19 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; | 20 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 20 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | 21 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 21 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 22 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| @@ -24,6 +25,8 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche | @@ -24,6 +25,8 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche | ||
| 24 | import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler; | 25 | import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler; |
| 25 | import jakarta.annotation.Resource; | 26 | import jakarta.annotation.Resource; |
| 26 | import lombok.extern.slf4j.Slf4j; | 27 | import lombok.extern.slf4j.Slf4j; |
| 28 | +import org.springframework.cache.annotation.CacheEvict; | ||
| 29 | +import org.springframework.cache.annotation.Cacheable; | ||
| 27 | import org.springframework.stereotype.Service; | 30 | import org.springframework.stereotype.Service; |
| 28 | import org.springframework.validation.annotation.Validated; | 31 | import org.springframework.validation.annotation.Validated; |
| 29 | 32 | ||
| @@ -60,6 +63,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -60,6 +63,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 60 | private IotSceneRuleTimerHandler timerHandler; | 63 | private IotSceneRuleTimerHandler timerHandler; |
| 61 | 64 | ||
| 62 | @Override | 65 | @Override |
| 66 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | ||
| 63 | public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) { | 67 | public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) { |
| 64 | IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class); | 68 | IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class); |
| 65 | sceneRuleMapper.insert(sceneRule); | 69 | sceneRuleMapper.insert(sceneRule); |
| @@ -71,6 +75,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -71,6 +75,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 71 | } | 75 | } |
| 72 | 76 | ||
| 73 | @Override | 77 | @Override |
| 78 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | ||
| 74 | public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) { | 79 | public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) { |
| 75 | // 校验存在 | 80 | // 校验存在 |
| 76 | validateSceneRuleExists(updateReqVO.getId()); | 81 | validateSceneRuleExists(updateReqVO.getId()); |
| @@ -83,6 +88,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -83,6 +88,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 83 | } | 88 | } |
| 84 | 89 | ||
| 85 | @Override | 90 | @Override |
| 91 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | ||
| 86 | public void updateSceneRuleStatus(Long id, Integer status) { | 92 | public void updateSceneRuleStatus(Long id, Integer status) { |
| 87 | // 1. 校验存在 | 93 | // 1. 校验存在 |
| 88 | validateSceneRuleExists(id); | 94 | validateSceneRuleExists(id); |
| @@ -105,6 +111,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -105,6 +111,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 105 | } | 111 | } |
| 106 | 112 | ||
| 107 | @Override | 113 | @Override |
| 114 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | ||
| 108 | public void deleteSceneRule(Long id) { | 115 | public void deleteSceneRule(Long id) { |
| 109 | // 1. 校验存在 | 116 | // 1. 校验存在 |
| 110 | validateSceneRuleExists(id); | 117 | validateSceneRuleExists(id); |
| @@ -149,15 +156,12 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -149,15 +156,12 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 149 | return sceneRuleMapper.selectListByStatus(status); | 156 | return sceneRuleMapper.selectListByStatus(status); |
| 150 | } | 157 | } |
| 151 | 158 | ||
| 152 | - // TODO @puhui999:缓存待实现 | ||
| 153 | @Override | 159 | @Override |
| 160 | + @Cacheable(value = RedisKeyConstants.SCENE_RULE_LIST, key = "#productId + '_' + #deviceId ") | ||
| 154 | @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略 | 161 | @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略 |
| 155 | public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) { | 162 | public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) { |
| 156 | // 1. 查询启用状态的规则场景 | 163 | // 1. 查询启用状态的规则场景 |
| 157 | - // TODO @puhui999:这里查询 enable 的; | ||
| 158 | - List<IotSceneRuleDO> list = sceneRuleMapper.selectList(); | ||
| 159 | - List<IotSceneRuleDO> enabledList = filterList(list, | ||
| 160 | - sceneRule -> CommonStatusEnum.isEnable(sceneRule.getStatus())); | 164 | + List<IotSceneRuleDO> enabledList = sceneRuleMapper.selectList(IotSceneRuleDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); |
| 161 | 165 | ||
| 162 | // 2. 根据 productKey 和 deviceName 进行匹配 | 166 | // 2. 根据 productKey 和 deviceName 进行匹配 |
| 163 | return filterList(enabledList, sceneRule -> { | 167 | return filterList(enabledList, sceneRule -> { |
| @@ -190,9 +194,10 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -190,9 +194,10 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 190 | 194 | ||
| 191 | @Override | 195 | @Override |
| 192 | public void executeSceneRuleByDevice(IotDeviceMessage message) { | 196 | public void executeSceneRuleByDevice(IotDeviceMessage message) { |
| 193 | - // TODO @puhui999:这里的 tenantId,通过设备获取; | ||
| 194 | - TenantUtils.execute(message.getTenantId(), () -> { | ||
| 195 | - // 1. 获得设备匹配的规则场景 | 197 | + // 1.1 这里的 tenantId,通过设备获取; |
| 198 | + IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); | ||
| 199 | + TenantUtils.execute(device.getTenantId(), () -> { | ||
| 200 | + // 1.2 获得设备匹配的规则场景 | ||
| 196 | List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message); | 201 | List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message); |
| 197 | if (CollUtil.isEmpty(sceneRules)) { | 202 | if (CollUtil.isEmpty(sceneRules)) { |
| 198 | return; | 203 | return; |
| @@ -238,14 +243,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | @@ -238,14 +243,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { | ||
| 238 | // 1. 匹配设备 | 243 | // 1. 匹配设备 |
| 239 | // TODO 缓存 @puhui999:可能需要 getSelf() | 244 | // TODO 缓存 @puhui999:可能需要 getSelf() |
| 240 | // 1.1 通过 deviceId 获取设备信息 | 245 | // 1.1 通过 deviceId 获取设备信息 |
| 241 | - IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); | 246 | + IotDeviceDO device = getSelf().deviceService.getDeviceFromCache(message.getDeviceId()); |
| 242 | if (device == null) { | 247 | if (device == null) { |
| 243 | log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId()); | 248 | log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId()); |
| 244 | return List.of(); | 249 | return List.of(); |
| 245 | } | 250 | } |
| 246 | 251 | ||
| 247 | // 1.2 通过 productId 获取产品信息 | 252 | // 1.2 通过 productId 获取产品信息 |
| 248 | - IotProductDO product = productService.getProductFromCache(device.getProductId()); | 253 | + IotProductDO product = getSelf().productService.getProductFromCache(device.getProductId()); |
| 249 | if (product == null) { | 254 | if (product == null) { |
| 250 | log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId()); | 255 | log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId()); |
| 251 | return List.of(); | 256 | return List.of(); |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java
| @@ -44,7 +44,7 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger | @@ -44,7 +44,7 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger | ||
| 44 | 44 | ||
| 45 | // 2. 对于服务调用触发器,通常只需要匹配服务标识符即可 | 45 | // 2. 对于服务调用触发器,通常只需要匹配服务标识符即可 |
| 46 | // 不需要检查操作符和值,因为服务调用本身就是触发条件 | 46 | // 不需要检查操作符和值,因为服务调用本身就是触发条件 |
| 47 | - // TODO @puhui999: 服务调用时校验输入参数是否匹配条件 | 47 | + // TODO @puhui999: 服务调用时校验输入参数是否匹配条件? |
| 48 | IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger); | 48 | IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger); |
| 49 | return true; | 49 | return true; |
| 50 | } | 50 | } |