4 Commity a0df8c4b14 ... 7bb385626c

Autor SHA1 Wiadomość Data
  james 7bb385626c 调整设备能耗`ConsumptionJob`触发频率为每小时整点 1 tydzień temu
  james 8799f46670 排查触发条件为设备触发触发方式为用量值的规则引擎没有生效的问题,调用查询时序数据库历史接口属性字段改为小写,同时调整查询时间格式 1 tydzień temu
  james 73e431e5a3 排查触发条件为设备触发触发方式为用量值的规则引擎没有生效的问题 1 tydzień temu
  james 1abe56018e 优化查询日志详情接口,将同一个规则下触发的所有动作合并到一个日志记录; 1 tydzień temu

+ 1 - 1
service-rule/service-rule-biz/src/main/java/com/usky/rule/cache/RuleEngineCache.java

@@ -19,7 +19,7 @@ public class RuleEngineCache {
     )
     public Cache<Long, List<DeviceTrigger>> consumptionTriggerCache() {
         return (new Cache2kBuilder<Long, List<DeviceTrigger>>() {
-        }).name("consumptionTriggerCache").eternal(false).expireAfterWrite(1L, TimeUnit.HOURS).entryCapacity(100000L).build();
+        }).name("consumptionTriggerCache").eternal(true).entryCapacity(100000L).build();
     }
 
     @Bean(

+ 10 - 1
service-rule/service-rule-biz/src/main/java/com/usky/rule/config/CronTaskManager.java

@@ -112,7 +112,16 @@ public class CronTaskManager {
     }
 
     public void performConsumptionTask() {
-        JobDetail consumptionJob = JobBuilder.newJob(ConsumptionJob.class).withIdentity("consumption", "device").build();
+        JobKey consumptionKey = JobKey.jobKey("consumption", "device");
+        try {
+            if (this.scheduler.checkExists(consumptionKey)) {
+                return;
+            }
+        } catch (SchedulerException e) {
+            throw new RuntimeException(e);
+        }
+
+        JobDetail consumptionJob = JobBuilder.newJob(ConsumptionJob.class).withIdentity(consumptionKey).build();
         CronTrigger consumptionTrigger = (CronTrigger)TriggerBuilder.newTrigger().forJob(consumptionJob).withIdentity("consumptionTrigger").withSchedule(CronScheduleBuilder.cronSchedule("0 0 * * * ?")).build();
 //        JobDetail spaceJob = JobBuilder.newJob(SpaceJob.class).withIdentity("space").build();
 //        CronTrigger spaceTrigger = (CronTrigger)TriggerBuilder.newTrigger().forJob(spaceJob).withIdentity("spaceTrigger", "space").withSchedule(CronScheduleBuilder.cronSchedule("0 0 * * * ?")).build();

+ 24 - 7
service-rule/service-rule-biz/src/main/java/com/usky/rule/crons/TriggerCronTask.java

@@ -59,9 +59,8 @@ public class TriggerCronTask implements ApplicationContextAware, InitializingBea
 
                 this.setDeviceConsumptionCache(ruleEngine.getId(), ruleEngineDetail);
             }
-
-            this.cronTaskManager.performConsumptionTask();
         }
+        this.cronTaskManager.performConsumptionTask();
     }
 
     private void startCronTask() {
@@ -85,13 +84,25 @@ public class TriggerCronTask implements ApplicationContextAware, InitializingBea
 
     }
 
+    /**
+     * 与库里的规则详情对齐能耗类设备触发器。去掉/改掉 consumption 时必须 remove,否则 ConsumptionJob 仍用旧缓存。
+     */
     public void setDeviceConsumptionCache(Long ruleEngineId, RuleEngineDetail ruleEngineDetail) {
+        if (ruleEngineId == null) {
+            return;
+        }
         List<DeviceTrigger> deviceTriggers = this.ruleEngineService.getDeviceTriggers(ruleEngineDetail.getTriggers());
-        if (deviceTriggers != null && !deviceTriggers.isEmpty()) {
-            List<DeviceTrigger> consumptionTrigger = (List)deviceTriggers.stream().filter((deviceTrigger) -> deviceTrigger.getMethod().equals("consumption")).collect(Collectors.toList());
-            if (!consumptionTrigger.isEmpty()) {
-                this.consumptionTriggerCache.put(ruleEngineId, consumptionTrigger);
-            }
+        if (deviceTriggers == null || deviceTriggers.isEmpty()) {
+            this.consumptionTriggerCache.remove(ruleEngineId);
+            return;
+        }
+        List<DeviceTrigger> consumptionTriggers = deviceTriggers.stream()
+                .filter((t) -> "consumption".equals(t.getMethod()))
+                .collect(Collectors.toList());
+        if (consumptionTriggers.isEmpty()) {
+            this.consumptionTriggerCache.remove(ruleEngineId);
+        } else {
+            this.consumptionTriggerCache.put(ruleEngineId, consumptionTriggers);
         }
 
 //        List<SpaceTrigger> spaceTriggers = this.ruleEngineService.getSpaceTriggers(ruleEngineDetail.getTriggers());
@@ -101,6 +112,12 @@ public class TriggerCronTask implements ApplicationContextAware, InitializingBea
 
     }
 
+    public void removeDeviceConsumptionCache(Long ruleEngineId) {
+        if (ruleEngineId != null) {
+            this.consumptionTriggerCache.remove(ruleEngineId);
+        }
+    }
+
     private void processCronTask(Long id, Long projectId, Long spaceId, RuleEngineDetail engineDetail, List<CronTrigger> cronTriggers) {
         List<CronConstraint> cronConstraints = this.ruleEngineService.getCronConstraints(engineDetail.getConstraints());
         List<DeviceConstraint> deviceConstraints = this.ruleEngineService.getDeviceConstraints(engineDetail.getConstraints());

+ 18 - 11
service-rule/service-rule-biz/src/main/java/com/usky/rule/jobs/ConsumptionJob.java

@@ -8,11 +8,10 @@ import com.usky.demo.domain.HistorysInnerRequestVO;
 import com.usky.demo.domain.HistorysInnerResultVO;
 import com.usky.demo.domain.MetricVO;
 import com.usky.rule.domain.RuleEngine;
-import com.usky.rule.vo.Result;
-import com.usky.rule.util.JsonUtil;
 import com.usky.rule.enums.TimeTypeEnum;
 import com.usky.rule.enums.TriggerTypeEnum;
 import com.usky.rule.enums.TriggerValueTypeEnum;
+import com.usky.rule.util.JsonUtil;
 import com.usky.rule.vo.DataPointVO;
 import com.usky.rule.vo.Condition;
 import com.usky.rule.vo.Expression;
@@ -30,6 +29,7 @@ import com.usky.rule.service.RuleEngineService;
 import java.math.BigDecimal;
 import java.time.DayOfWeek;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
 import javax.annotation.Resource;
@@ -48,6 +48,8 @@ import org.springframework.util.CollectionUtils;
 @DisallowConcurrentExecution
 @Slf4j
 public class ConsumptionJob implements Job {
+
+    private static final DateTimeFormatter CONSUMPTION_TIME_DISPLAY = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
     @Resource
     private Cache<Long, List<DeviceTrigger>> consumptionTriggerCache;
     @Resource
@@ -64,15 +66,19 @@ public class ConsumptionJob implements Job {
     }
 
     public void execute(JobExecutionContext context) throws JobExecutionException {
-        LocalDateTime[] times = new LocalDateTime[2];
+        String[] times = new String[2];
         LocalDateTime now = LocalDateTime.now();
 
         for(CacheEntry<Long, List<DeviceTrigger>> entry : this.consumptionTriggerCache.entries()) {
             log.info("consumptionTriggerCache: {}, now: {}", entry.getKey(), now);
             Long engineId = (Long)entry.getKey();
             RuleEngine ruleEngine = (RuleEngine)this.ruleEngineService.getById(engineId);
+            log.info("ruleEngine: {}", ruleEngine);
+            if (ruleEngine == null || ruleEngine.getStatus() == null || ruleEngine.getStatus() != 1) {
+                continue;
+            }
             Long spaceId = ruleEngine.getSpaceId();
-            RuleEngineDetail ruleEngineDetail = (RuleEngineDetail)JsonUtil.toObject(ruleEngine.getDetail(), RuleEngineDetail.class);
+            RuleEngineDetail ruleEngineDetail = (RuleEngineDetail) JsonUtil.toObject(ruleEngine.getDetail(), RuleEngineDetail.class);
             List<RuleEngineAction> actions = this.ruleEngineService.getActions(ruleEngineDetail.getActions());
             if (!actions.isEmpty()) {
                 RuleEngineDetailLog ruleEngineDetailLog = new RuleEngineDetailLog();
@@ -104,14 +110,14 @@ public class ConsumptionJob implements Job {
 
                                 HistorysInnerRequestVO requestVO = new HistorysInnerRequestVO();
                                 requestVO.setDeviceuuid(Collections.singletonList(device.getDeviceUuid()));
-                                requestVO.setMetrics(Collections.singletonList(identifier));
-                                requestVO.setStartTime(times[0].toString());
-                                requestVO.setEndTime(times[1].toString());
+                                requestVO.setMetrics(Collections.singletonList(identifier.toLowerCase()));
+                                requestVO.setStartTime(times[0]);
+                                requestVO.setEndTime(times[1]);
                                 ApiResult<List<HistorysInnerResultVO>> historyApi = remoteTsdbProxyService.queryHistoryDeviceData(requestVO);
                                 List<HistorysInnerResultVO> result = historyApi != null && historyApi.getData() != null
                                         ? historyApi.getData()
                                         : Collections.emptyList();
-                                List<DataPointVO> dataPointVOList = findDataPointsForMetric(result, device.getDeviceUuid(), identifier);
+                                List<DataPointVO> dataPointVOList = findDataPointsForMetric(result, device.getDeviceUuid(), identifier.toLowerCase());
                                 if (dataPointVOList.isEmpty()) {
                                     boolConstraintExp.append(false);
                                 } else {
@@ -160,7 +166,7 @@ public class ConsumptionJob implements Job {
 
     }
 
-    public static void initStartTimeAndEndTime(LocalDateTime now, LocalDateTime[] times, TimeRange timeRange) {
+    public static void initStartTimeAndEndTime(LocalDateTime now, String[] times, TimeRange timeRange) {
         Integer start = timeRange.getStart();
         Integer end = timeRange.getEnd();
         Assert.notNull(start, "start不能为空");
@@ -225,8 +231,9 @@ public class ConsumptionJob implements Job {
                 throw new IllegalArgumentException("不支持的时间类型: " + typeEnum);
         }
 
-        times[0] = startTime;
-        times[1] = endTime;
+        times[0] = startTime.format(CONSUMPTION_TIME_DISPLAY);
+        times[1] = endTime.format(CONSUMPTION_TIME_DISPLAY);
+        log.debug("initStartTimeAndEndTime type={} startTime={} endTime={}", typeEnum, times[0], times[1]);
     }
 
     public static boolean preAssertFalse(StringBuilder boolConstraintExp, String operator) {

+ 13 - 11
service-rule/service-rule-biz/src/main/java/com/usky/rule/service/impl/RuleEngineDetailServiceImpl.java

@@ -33,20 +33,21 @@ public class RuleEngineDetailServiceImpl implements RuleEngineDetailService {
 
     public Boolean save(RuleEngineDTO dto) {
         if (dto.getStatus() != null && dto.getStatus() == 0) {
+            this.triggerCronTask.removeDeviceConsumptionCache(dto.getId());
             return true;
-        } else if (StringUtils.isBlank(dto.getDetail())) {
+        }
+        if (StringUtils.isBlank(dto.getDetail())) {
+            this.triggerCronTask.removeDeviceConsumptionCache(dto.getId());
             return true;
-        } else {
-            RuleEngineDetail ruleEngineDetail = (RuleEngineDetail)JsonUtil.toObject(dto.getDetail(), RuleEngineDetail.class);
-            List<RuleEngineAction> actions = this.ruleEngineService.getActions(ruleEngineDetail.getActions());
-            if (actions != null && !actions.isEmpty()) {
-                this.triggerCronTask.setDeviceConsumptionCache(dto.getId(), ruleEngineDetail);
-                this.createCronTask(dto, ruleEngineDetail, actions);
-                return true;
-            } else {
-                return true;
-            }
         }
+        RuleEngineDetail ruleEngineDetail = (RuleEngineDetail)JsonUtil.toObject(dto.getDetail(), RuleEngineDetail.class);
+        // 必须先同步缓存:与 actions 是否为空无关,否则仅改触发器/去掉能耗时仍沿用旧 consumption 列表
+        this.triggerCronTask.setDeviceConsumptionCache(dto.getId(), ruleEngineDetail);
+        List<RuleEngineAction> actions = this.ruleEngineService.getActions(ruleEngineDetail.getActions());
+        if (actions != null && !actions.isEmpty()) {
+            this.createCronTask(dto, ruleEngineDetail, actions);
+        }
+        return true;
     }
 
     private void createCronTask(RuleEngineDTO dto, RuleEngineDetail ruleEngineDetail, List<RuleEngineAction> actions) {
@@ -70,6 +71,7 @@ public class RuleEngineDetailServiceImpl implements RuleEngineDetailService {
     public Boolean remove(Long id) {
         Assert.notNull(id, "id不能为空");
         this.historyRecordCache.deleteConditions(id);
+        this.triggerCronTask.removeDeviceConsumptionCache(id);
         return this.cronTaskManager.deleteAllJobsInJobGroup(id);
     }
 

+ 2 - 2
service-rule/service-rule-biz/src/main/java/com/usky/rule/service/impl/RuleEngineServiceImpl.java

@@ -129,7 +129,7 @@ public class RuleEngineServiceImpl extends AbstractCrudService<RuleEngineMapper,
     @Override
     public RuleEngine getById(Long id) {
         Integer tenantId = SecurityUtils.getTenantId();
-        if (tenantId == 0) {
+        if (tenantId == 0 || tenantId == null) {
             return getBaseMapper().selectById(id, null);
         }else{
             return getBaseMapper().selectById(id, SecurityUtils.getTenantId());
@@ -193,7 +193,7 @@ public class RuleEngineServiceImpl extends AbstractCrudService<RuleEngineMapper,
         queryWrapper.in(CollectionUtils.isNotEmpty(ids), RuleEngine::getSpaceId, ids)
                 .like(StringUtils.isNotBlank(request.getName()),RuleEngine::getName, request.getName())
                 .eq(request.getStatus() != null,RuleEngine::getStatus,request.getStatus())
-                .eq(RuleEngine::getTenantId,SecurityUtils.getTenantId());
+                .eq(SecurityUtils.getTenantId() != 0 && SecurityUtils.getTenantId() != null,RuleEngine::getTenantId,SecurityUtils.getTenantId());
         List<RuleEngine> ruleEngines = this.list(queryWrapper);
         return ruleEngines;
     }

+ 1 - 1
service-rule/service-rule-biz/src/main/java/com/usky/rule/subscribe/TriggerDeviceUtil.java

@@ -355,7 +355,7 @@ public class TriggerDeviceUtil {
                 List<Condition> meetConstraintConditionList = new ArrayList();
                 deviceTriggerLog.setId(deviceId);
                 deviceTriggerLog.setMethod("acq");
-//                deviceTriggerLog.setName(this.deviceService.getName(deviceId));
+                deviceTriggerLog.setName(deviceConstraint.getDevices().get(0).getName());
                 deviceTriggerLog.setConditions(meetConstraintConditionList);
                 deviceTriggerLogs.add(deviceTriggerLog);
                 List<Condition> identifierConditions = deviceConstraint.getConditions();

+ 19 - 18
service-rule/service-rule-biz/src/main/java/com/usky/rule/util/RuleEngineUtil.java

@@ -83,26 +83,27 @@ public class RuleEngineUtil {
                 baseLogs.add(baseLog);
                 ruleEngineLog.setTenantId(((AlarmEventAction) ruleEngineAction).getDevices().get(0).getTenantId());
             }
-            ruleEngineLog.setDetail(JsonUtil.toJson(ruleEngineDetail));
-            ruleEngineLog.setRuleEngineId(ruleEngineId);
-            ruleEngineLog.setRuleEngineName(ruleEngineName);
-            ruleEngineLog.setAutoTrigger((byte) (isAuto ? 1 : 0));
-            ruleEngineLog.setProjectId(projectId);
-            ruleEngineLog.setAction(String.join(",", deviceActionTypes));
-            ruleEngineLog.setTriggerType(triggerType);
-            ruleEngineLog.setUpdateTime(now);
-            ruleEngineLog.setCreateTime(now);
-            ruleEngineLog.setCreatedBy("admin");
-            ruleEngineLog.setUpdatedBy("admin");
-            if(!SecurityUtils.getUsername().isEmpty()) {
-                ruleEngineLog.setCreatedBy(SecurityUtils.getUsername());
-                ruleEngineLog.setUpdatedBy(SecurityUtils.getUsername());
-                ruleEngineLog.setTenantId(SecurityUtils.getTenantId());
-            }
-            ruleEngineLog.setTime(now);
-            this.ruleEngineLogService.save(ruleEngineLog);
         }
 
+        ruleEngineLog.setDetail(JsonUtil.toJson(ruleEngineDetail));
+        ruleEngineLog.setRuleEngineId(ruleEngineId);
+        ruleEngineLog.setRuleEngineName(ruleEngineName);
+        ruleEngineLog.setAutoTrigger((byte) (isAuto ? 1 : 0));
+        ruleEngineLog.setProjectId(projectId);
+        ruleEngineLog.setAction(String.join(",", deviceActionTypes));
+        ruleEngineLog.setTriggerType(triggerType);
+        ruleEngineLog.setUpdateTime(now);
+        ruleEngineLog.setCreateTime(now);
+        ruleEngineLog.setCreatedBy("admin");
+        ruleEngineLog.setUpdatedBy("admin");
+        if(!SecurityUtils.getUsername().isEmpty()) {
+            ruleEngineLog.setCreatedBy(SecurityUtils.getUsername());
+            ruleEngineLog.setUpdatedBy(SecurityUtils.getUsername());
+            ruleEngineLog.setTenantId(SecurityUtils.getTenantId());
+        }
+        ruleEngineLog.setTime(now);
+        this.ruleEngineLogService.save(ruleEngineLog);
+
     }
 
     @NotNull