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 | 76 | */ |
| 77 | 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 | 16 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 17 | 17 | import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; |
| 18 | 18 | import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper; |
| 19 | +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | |
| 19 | 20 | import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum; |
| 20 | 21 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 21 | 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 | 25 | import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler; |
| 25 | 26 | import jakarta.annotation.Resource; |
| 26 | 27 | import lombok.extern.slf4j.Slf4j; |
| 28 | +import org.springframework.cache.annotation.CacheEvict; | |
| 29 | +import org.springframework.cache.annotation.Cacheable; | |
| 27 | 30 | import org.springframework.stereotype.Service; |
| 28 | 31 | import org.springframework.validation.annotation.Validated; |
| 29 | 32 | |
| ... | ... | @@ -60,6 +63,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 60 | 63 | private IotSceneRuleTimerHandler timerHandler; |
| 61 | 64 | |
| 62 | 65 | @Override |
| 66 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | |
| 63 | 67 | public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) { |
| 64 | 68 | IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class); |
| 65 | 69 | sceneRuleMapper.insert(sceneRule); |
| ... | ... | @@ -71,6 +75,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 71 | 75 | } |
| 72 | 76 | |
| 73 | 77 | @Override |
| 78 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | |
| 74 | 79 | public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) { |
| 75 | 80 | // 校验存在 |
| 76 | 81 | validateSceneRuleExists(updateReqVO.getId()); |
| ... | ... | @@ -83,6 +88,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 83 | 88 | } |
| 84 | 89 | |
| 85 | 90 | @Override |
| 91 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | |
| 86 | 92 | public void updateSceneRuleStatus(Long id, Integer status) { |
| 87 | 93 | // 1. 校验存在 |
| 88 | 94 | validateSceneRuleExists(id); |
| ... | ... | @@ -105,6 +111,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 105 | 111 | } |
| 106 | 112 | |
| 107 | 113 | @Override |
| 114 | + @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true) | |
| 108 | 115 | public void deleteSceneRule(Long id) { |
| 109 | 116 | // 1. 校验存在 |
| 110 | 117 | validateSceneRuleExists(id); |
| ... | ... | @@ -149,15 +156,12 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 149 | 156 | return sceneRuleMapper.selectListByStatus(status); |
| 150 | 157 | } |
| 151 | 158 | |
| 152 | - // TODO @puhui999:缓存待实现 | |
| 153 | 159 | @Override |
| 160 | + @Cacheable(value = RedisKeyConstants.SCENE_RULE_LIST, key = "#productId + '_' + #deviceId ") | |
| 154 | 161 | @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略 |
| 155 | 162 | public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) { |
| 156 | 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 | 166 | // 2. 根据 productKey 和 deviceName 进行匹配 |
| 163 | 167 | return filterList(enabledList, sceneRule -> { |
| ... | ... | @@ -190,9 +194,10 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 190 | 194 | |
| 191 | 195 | @Override |
| 192 | 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 | 201 | List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message); |
| 197 | 202 | if (CollUtil.isEmpty(sceneRules)) { |
| 198 | 203 | return; |
| ... | ... | @@ -238,14 +243,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService { |
| 238 | 243 | // 1. 匹配设备 |
| 239 | 244 | // TODO 缓存 @puhui999:可能需要 getSelf() |
| 240 | 245 | // 1.1 通过 deviceId 获取设备信息 |
| 241 | - IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); | |
| 246 | + IotDeviceDO device = getSelf().deviceService.getDeviceFromCache(message.getDeviceId()); | |
| 242 | 247 | if (device == null) { |
| 243 | 248 | log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId()); |
| 244 | 249 | return List.of(); |
| 245 | 250 | } |
| 246 | 251 | |
| 247 | 252 | // 1.2 通过 productId 获取产品信息 |
| 248 | - IotProductDO product = productService.getProductFromCache(device.getProductId()); | |
| 253 | + IotProductDO product = getSelf().productService.getProductFromCache(device.getProductId()); | |
| 249 | 254 | if (product == null) { |
| 250 | 255 | log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId()); |
| 251 | 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 | 44 | |
| 45 | 45 | // 2. 对于服务调用触发器,通常只需要匹配服务标识符即可 |
| 46 | 46 | // 不需要检查操作符和值,因为服务调用本身就是触发条件 |
| 47 | - // TODO @puhui999: 服务调用时校验输入参数是否匹配条件 | |
| 47 | + // TODO @puhui999: 服务调用时校验输入参数是否匹配条件? | |
| 48 | 48 | IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger); |
| 49 | 49 | return true; |
| 50 | 50 | } | ... | ... |