| New file |
| | |
| | | package com.zy.asrs.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.service.RuntimeConfigService; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | |
| | | @Service("runtimeConfigService") |
| | | public class RuntimeConfigServiceImpl implements RuntimeConfigService { |
| | | |
| | | private static final LinkedHashMap<String, RuntimeConfigRule> RUNTIME_CONFIG_RULE_MAP = buildRuntimeConfigRuleMap(); |
| | | |
| | | @Autowired |
| | | private ConfigService configService; |
| | | |
| | | @Override |
| | | @Transactional |
| | | public Map<String, Object> updateRuntimeConfig(Map<String, Object> configMap) { |
| | | if (configMap == null || configMap.isEmpty()) { |
| | | throw new CoolException("åæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | LinkedHashMap<String, String> normalizedMap = new LinkedHashMap<>(); |
| | | for (Map.Entry<String, Object> entry : configMap.entrySet()) { |
| | | String code = entry.getKey(); |
| | | RuntimeConfigRule rule = RUNTIME_CONFIG_RULE_MAP.get(code); |
| | | if (rule == null) { |
| | | throw new CoolException("䏿¯æçè¿è¡åæ°: " + code); |
| | | } |
| | | |
| | | Config config = getConfig(code); |
| | | if (config == null) { |
| | | throw new CoolException("è¿è¡åæ°ä¸åå¨: " + code); |
| | | } |
| | | if (!Short.valueOf((short) 1).equals(config.getStatus())) { |
| | | throw new CoolException("è¿è¡åæ°å·²ç¦ç¨: " + code); |
| | | } |
| | | |
| | | normalizedMap.put(code, rule.normalize(code, entry.getValue())); |
| | | } |
| | | |
| | | LinkedHashMap<String, String> changedMap = saveChangedConfig(normalizedMap); |
| | | if (!changedMap.isEmpty()) { |
| | | configService.refreshSystemConfigCache(); |
| | | } |
| | | |
| | | LinkedHashMap<String, Object> result = new LinkedHashMap<>(); |
| | | result.put("changed", changedMap); |
| | | result.put("current", buildRuntimeConfigSnapshot(normalizedMap.keySet())); |
| | | return result; |
| | | } |
| | | |
| | | private LinkedHashMap<String, String> saveChangedConfig(LinkedHashMap<String, String> normalizedMap) { |
| | | LinkedHashMap<String, String> changedMap = new LinkedHashMap<>(); |
| | | for (Map.Entry<String, String> entry : normalizedMap.entrySet()) { |
| | | Config config = getConfig(entry.getKey()); |
| | | if (config == null) { |
| | | throw new CoolException("è¿è¡åæ°ä¸åå¨: " + entry.getKey()); |
| | | } |
| | | if (Objects.equals(config.getValue(), entry.getValue())) { |
| | | continue; |
| | | } |
| | | config.setValue(entry.getValue()); |
| | | if (!configService.updateById(config)) { |
| | | throw new CoolException("ä¿å失败: " + entry.getKey()); |
| | | } |
| | | changedMap.put(entry.getKey(), entry.getValue()); |
| | | } |
| | | return changedMap; |
| | | } |
| | | |
| | | private LinkedHashMap<String, String> buildRuntimeConfigSnapshot(Set<String> codeSet) { |
| | | LinkedHashMap<String, String> result = new LinkedHashMap<>(); |
| | | for (String code : codeSet) { |
| | | Config config = getConfig(code); |
| | | if (config != null) { |
| | | result.put(code, config.getValue()); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private Config getConfig(String code) { |
| | | return configService.getOne(new QueryWrapper<Config>().eq("code", code).last("limit 1")); |
| | | } |
| | | |
| | | private static LinkedHashMap<String, RuntimeConfigRule> buildRuntimeConfigRuleMap() { |
| | | LinkedHashMap<String, RuntimeConfigRule> ruleMap = new LinkedHashMap<>(); |
| | | putIntRule(ruleMap, "conveyorStationTaskLimit", 1, 1000); |
| | | putIntRule(ruleMap, "stationMaxTaskCountLimit", 0, 1000); |
| | | putIntRule(ruleMap, "stationCommandSendLength", 1, 200); |
| | | putRatioRule(ruleMap, "stationCommandSegmentAdvanceRatio"); |
| | | putIntRule(ruleMap, "stationCommandConfigRefreshSeconds", 5, 300); |
| | | putIntRule(ruleMap, "stationV5SegmentExecutorPoolSize", 16, 512); |
| | | putIntRule(ruleMap, "stationV5SegmentExecutorQueueCapacity", 64, 4096); |
| | | putIntRule(ruleMap, "crnOutBatchRunningLimit", 0, 1000); |
| | | putBooleanRule(ruleMap, "crnOutRequireStationOutEnable"); |
| | | putIntRule(ruleMap, "deviceCommandAutoRollbackLimit", 1, 100); |
| | | putBooleanRule(ruleMap, "checkDeepLocOutTaskBlockReport"); |
| | | return ruleMap; |
| | | } |
| | | |
| | | private static void putIntRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap, |
| | | String code, |
| | | int min, |
| | | int max) { |
| | | ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.INT, min, max)); |
| | | } |
| | | |
| | | private static void putRatioRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap, String code) { |
| | | ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.RATIO, 0, 100)); |
| | | } |
| | | |
| | | private static void putBooleanRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap, String code) { |
| | | ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.BOOLEAN, 0, 0)); |
| | | } |
| | | |
| | | private enum RuntimeConfigValueType { |
| | | INT, |
| | | RATIO, |
| | | BOOLEAN |
| | | } |
| | | |
| | | private static class RuntimeConfigRule { |
| | | |
| | | private final RuntimeConfigValueType valueType; |
| | | private final int min; |
| | | private final int max; |
| | | |
| | | private RuntimeConfigRule(RuntimeConfigValueType valueType, int min, int max) { |
| | | this.valueType = valueType; |
| | | this.min = min; |
| | | this.max = max; |
| | | } |
| | | |
| | | private String normalize(String code, Object rawValue) { |
| | | if (rawValue == null) { |
| | | throw new CoolException(code + " åæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | String value = String.valueOf(rawValue).trim(); |
| | | if (value.isEmpty()) { |
| | | throw new CoolException(code + " åæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (RuntimeConfigValueType.BOOLEAN.equals(valueType)) { |
| | | return normalizeBoolean(code, value); |
| | | } |
| | | if (RuntimeConfigValueType.RATIO.equals(valueType)) { |
| | | return normalizeRatio(code, value); |
| | | } |
| | | return normalizeInt(code, value); |
| | | } |
| | | |
| | | private String normalizeBoolean(String code, String value) { |
| | | if ("Y".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "1".equals(value)) { |
| | | return "Y"; |
| | | } |
| | | if ("N".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value) || "0".equals(value)) { |
| | | return "N"; |
| | | } |
| | | throw new CoolException(code + " ä»
æ¯æ Y/Nãtrue/false æ 1/0"); |
| | | } |
| | | |
| | | private String normalizeRatio(String code, String value) { |
| | | String text = value; |
| | | boolean percentText = text.endsWith("%"); |
| | | if (percentText) { |
| | | text = text.substring(0, text.length() - 1).trim(); |
| | | } |
| | | double parsed; |
| | | try { |
| | | parsed = Double.parseDouble(text); |
| | | } catch (Exception e) { |
| | | throw new CoolException(code + " å¿
须为 0~1 æ¯ä¾æ 0~100 ç¾åæ¯"); |
| | | } |
| | | if (parsed < 0d || parsed > 100d) { |
| | | throw new CoolException(code + " å¿
须为 0~1 æ¯ä¾æ 0~100 ç¾åæ¯"); |
| | | } |
| | | if (percentText || parsed > 1d) { |
| | | parsed = parsed / 100d; |
| | | } |
| | | return stripTrailingZero(parsed); |
| | | } |
| | | |
| | | private String normalizeInt(String code, String value) { |
| | | int parsed; |
| | | try { |
| | | parsed = Integer.parseInt(value); |
| | | } catch (Exception e) { |
| | | throw new CoolException(code + " å¿
é¡»ä¸ºæ´æ°"); |
| | | } |
| | | if (parsed < min || parsed > max) { |
| | | throw new CoolException(code + " å¿
é¡»å¨ " + min + "~" + max + " èå´å
"); |
| | | } |
| | | return String.valueOf(parsed); |
| | | } |
| | | |
| | | private String stripTrailingZero(double value) { |
| | | String text = java.math.BigDecimal.valueOf(value).stripTrailingZeros().toPlainString(); |
| | | return "-0".equals(text) ? "0" : text; |
| | | } |
| | | } |
| | | } |